ScriptCollection 3.4.58__py3-none-any.whl → 3.5.0__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.
@@ -1,4 +1,4 @@
1
- import os
1
+ import sys
2
2
  from subprocess import PIPE, Popen
3
3
  from .GeneralUtilities import GeneralUtilities
4
4
  from .ProgramRunnerBase import ProgramRunnerBase
@@ -13,14 +13,10 @@ class ProgramRunnerPopen(ProgramRunnerBase):
13
13
  # "shell=True" is not allowed because it is not recommended and also something like
14
14
  # "ScriptCollectionCore().run_program('curl', 'https://example.com/dataset?id=1&format=json')"
15
15
  # would not be possible anymore because the ampersand will be treated as shell-command.
16
- cwd = os.getcwd()
17
16
  try:
18
- os.chdir(working_directory)
19
- result = Popen(arguments_for_process, stdout=PIPE, stderr=PIPE, shell=False) # pylint: disable=consider-using-with
17
+ result = Popen(arguments_for_process, cwd=working_directory, stdin=sys.stdin, stdout=PIPE, stderr=PIPE, shell=False) # pylint: disable=consider-using-with
20
18
  except FileNotFoundError as fileNotFoundError:
21
19
  raise FileNotFoundError(f"Starting '{program}' in '{working_directory}' resulted in a FileNotFoundError: '{fileNotFoundError.filename}'")
22
- finally:
23
- os.chdir(cwd)
24
20
  return result
25
21
 
26
22
  # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
@@ -1,3 +1,4 @@
1
+ import time
1
2
  from datetime import timedelta, datetime
2
3
  import json
3
4
  import binascii
@@ -28,7 +29,7 @@ from .ProgramRunnerPopen import ProgramRunnerPopen
28
29
  from .ProgramRunnerEpew import ProgramRunnerEpew, CustomEpewArgument
29
30
 
30
31
 
31
- version = "3.4.58"
32
+ version = "3.5.0"
32
33
  __version__ = version
33
34
 
34
35
 
@@ -176,7 +177,7 @@ class ScriptCollectionCore:
176
177
 
177
178
  @GeneralUtilities.check_arguments
178
179
  def git_commit_is_ancestor(self, repository_folder: str, ancestor: str, descendant: str = "HEAD") -> bool:
179
- exit_code = self.run_program_argsasarray("git", ["merge-base", "--is-ancestor", ancestor, descendant], repository_folder, throw_exception_if_exitcode_is_not_zero=False)[0]
180
+ exit_code = self.run_program_argsasarray("git", ["merge-base", "--is-ancestor", ancestor, descendant], repository_folder, throw_exception_if_exitcode_is_not_zero=False)[0]
180
181
  if exit_code == 0:
181
182
  return True
182
183
  elif exit_code == 1:
@@ -222,12 +223,12 @@ class ScriptCollectionCore:
222
223
 
223
224
  @GeneralUtilities.check_arguments
224
225
  def git_get_commit_id(self, repository_folder: str, commit: str = "HEAD") -> str:
225
- result: tuple[int, str, str, int] = self.run_program_argsasarray("git", ["rev-parse", "--verify", commit], repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
226
+ result: tuple[int, str, str, int] = self.run_program_argsasarray("git", ["rev-parse", "--verify", commit], repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
226
227
  return result[1].replace('\n', '')
227
228
 
228
229
  @GeneralUtilities.check_arguments
229
230
  def git_get_commit_date(self, repository_folder: str, commit: str = "HEAD") -> datetime:
230
- result: tuple[int, str, str, int] = self.run_program_argsasarray("git", ["show", "-s", "--format=%ci", commit], repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
231
+ result: tuple[int, str, str, int] = self.run_program_argsasarray("git", ["show", "-s", "--format=%ci", commit], repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
231
232
  date_as_string = result[1].replace('\n', '')
232
233
  result = datetime.strptime(date_as_string, '%Y-%m-%d %H:%M:%S %z')
233
234
  return result
@@ -1150,7 +1151,7 @@ class ScriptCollectionCore:
1150
1151
  # <run programs>
1151
1152
 
1152
1153
  @GeneralUtilities.check_arguments
1153
- def __run_program_argsasarray_async_helper(self, program: str, arguments_as_array: list[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, custom_argument: object = None) -> Popen:
1154
+ def __run_program_argsasarray_async_helper(self, program: str, arguments_as_array: list[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, custom_argument: object = None) -> Popen:
1154
1155
  # Verbosity:
1155
1156
  # 0=Quiet (No output will be printed.)
1156
1157
  # 1=Normal (If the exitcode of the executed program is not 0 then the StdErr will be printed.)
@@ -1180,105 +1181,94 @@ class ScriptCollectionCore:
1180
1181
  # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
1181
1182
 
1182
1183
  @GeneralUtilities.check_arguments
1183
- def run_program_argsasarray(self, program: str, arguments_as_array: list[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) -> tuple[int, str, str, int]:
1184
- mock_loader_result = self.__try_load_mock(program, ' '.join(arguments_as_array), working_directory)
1185
- if mock_loader_result[0]:
1186
- return mock_loader_result[1]
1187
-
1188
- if arguments_for_log is None:
1189
- arguments_for_log = arguments_as_array
1190
-
1191
- arguments_for_log_as_string = ' '.join(arguments_for_log)
1192
- cmd = f'{working_directory}>{program} {arguments_for_log_as_string}'
1193
- if GeneralUtilities.string_is_none_or_whitespace(title):
1194
- info_for_log = cmd
1195
- else:
1196
- info_for_log = title
1197
-
1198
- epew_will_be_used = isinstance(self.program_runner, ProgramRunnerEpew)
1199
- program_manages_output_itself = epew_will_be_used and False # TODO fix stdout-/stderr-reading-block below
1200
- program_manages_logging_itself = epew_will_be_used
1201
-
1202
- process = 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)
1203
- pid = process.pid
1204
-
1205
- if program_manages_output_itself:
1206
- stdout_readable = process.stdout.readable()
1207
- stderr_readable = process.stderr.readable()
1208
- while stdout_readable or stderr_readable:
1209
-
1210
- if stdout_readable:
1211
- stdout_line = GeneralUtilities.bytes_to_string(process.stdout.readline()).strip()
1212
- if (len(stdout_line)) > 0:
1213
- GeneralUtilities.write_message_to_stdout(stdout_line)
1214
-
1215
- if stderr_readable:
1216
- stderr_line = GeneralUtilities.bytes_to_string(process.stderr.readline()).strip()
1217
- if (len(stderr_line)) > 0:
1218
- GeneralUtilities.write_message_to_stderr(stderr_line)
1219
-
1220
- stdout_readable = process.stdout.readable()
1221
- stderr_readable = process.stderr.readable()
1222
-
1223
- stdout, stderr = process.communicate()
1224
- exit_code = process.wait()
1225
- stdout = GeneralUtilities.bytes_to_string(stdout).replace('\r', '')
1226
- stderr = GeneralUtilities.bytes_to_string(stderr).replace('\r', '')
1184
+ def run_program_argsasarray(self, program: str, arguments_as_array: list[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) -> tuple[int, str, str, int]:
1185
+ try:
1186
+ mock_loader_result = self.__try_load_mock(program, ' '.join(arguments_as_array), working_directory)
1187
+ if mock_loader_result[0]:
1188
+ return mock_loader_result[1]
1189
+
1190
+ if arguments_for_log is None:
1191
+ arguments_for_log = arguments_as_array
1192
+
1193
+ arguments_for_exception_as_string = ' '.join(arguments_for_log)
1194
+
1195
+ process: Popen = 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)
1196
+ pid = process.pid
1197
+
1198
+ stdout_lines=list[str]()
1199
+ stderr_lines=list[str]()
1200
+
1201
+ live_console_output_printing=1<verbosity
1202
+
1203
+ log_to_file=log_file is not None
1204
+ if log_to_file:
1205
+ GeneralUtilities.ensure_file_exists(log_file)
1206
+ def stream_process(process):
1207
+ try:
1208
+
1209
+ go = process.poll() is None
1210
+ for line in process.stdout:
1211
+ line_str=GeneralUtilities.bytes_to_string(line).strip().replace('\r', '').replace('\n', '')
1212
+ stdout_lines.append(line_str)
1213
+ if live_console_output_printing:
1214
+ GeneralUtilities.write_message_to_stdout(line_str)
1215
+ if log_to_file:
1216
+ GeneralUtilities.append_line_to_file(log_file, line_str)
1217
+ for line in process.stderr:
1218
+ line_str=GeneralUtilities.bytes_to_string(line).strip().replace('\r', '').replace('\n', '')
1219
+ stderr_lines.append(line_str)
1220
+ if live_console_output_printing:
1221
+ if print_errors_as_information:
1222
+ GeneralUtilities.write_message_to_stdout(line_str)
1223
+ else:
1224
+ GeneralUtilities.write_message_to_stderr(line_str)
1225
+ if log_to_file:
1226
+ GeneralUtilities.append_line_to_file(log_file, line_str)
1227
+ return go
1228
+ except Exception:
1229
+ return None
1230
+ while stream_process(process):
1231
+ time.sleep(0.1)
1232
+
1233
+ exit_code = process.poll()
1234
+ stdout = '\n'.join(stdout_lines)
1235
+ stderr = '\n'.join(stderr_lines)
1236
+
1237
+ if arguments_for_exception_as_string is None:
1238
+ arguments_for_exception_as_string = ' '.join(arguments_as_array)
1239
+ else:
1240
+ arguments_for_exception_as_string = ' '.join(arguments_for_log)
1227
1241
 
1228
- if arguments_for_log_as_string is None:
1229
- arguments_for_log_as_string = ' '.join(arguments_as_array)
1230
- else:
1231
- arguments_for_log_as_string = ' '.join(arguments_for_log)
1232
1242
 
1233
- if GeneralUtilities.string_is_none_or_whitespace(title):
1234
- info_for_log = cmd
1235
- else:
1236
- info_for_log = title
1243
+ if throw_exception_if_exitcode_is_not_zero and exit_code != 0:
1244
+ arguments_for_exception_as_string = ' '.join(arguments_for_log)
1245
+ raise ValueError(f"Program '{working_directory}>{program} {arguments_for_exception_as_string}' resulted in exitcode {exit_code}. (StdOut: '{stdout}', StdErr: '{stderr}')")
1237
1246
 
1238
- if not program_manages_logging_itself and log_file is not None:
1239
- GeneralUtilities.ensure_file_exists(log_file)
1240
- GeneralUtilities.append_line_to_file(log_file, stdout)
1241
- GeneralUtilities.append_line_to_file(log_file, stderr)
1242
-
1243
- if not program_manages_output_itself:
1244
- if verbosity == 1 and exit_code != 0:
1245
- self.__write_error_output(print_errors_as_information, stderr)
1246
- if verbosity == 2:
1247
- GeneralUtilities.write_message_to_stdout(stdout)
1248
- self.__write_error_output(print_errors_as_information, stderr)
1249
- if verbosity == 3:
1250
- GeneralUtilities.write_message_to_stdout(stdout)
1251
- self.__write_error_output(print_errors_as_information, stderr)
1252
- formatted = self.__format_program_execution_information(title=info_for_log, program=program, argument=arguments_for_log_as_string, workingdirectory=working_directory)
1253
- GeneralUtilities.write_message_to_stdout(f"Finished '{info_for_log}'. Details: '{formatted}")
1254
-
1255
- if throw_exception_if_exitcode_is_not_zero and exit_code != 0:
1256
- arguments_for_log_as_string = ' '.join(arguments_for_log)
1257
- raise ValueError(f"Program '{working_directory}>{program} {arguments_for_log_as_string}' resulted in exitcode {exit_code}. (StdOut: '{stdout}', StdErr: '{stderr}')")
1258
-
1259
- result = (exit_code, stdout, stderr, pid)
1260
- return result
1247
+ result = (exit_code, stdout, stderr, pid)
1248
+ return result
1249
+ except Exception as e:
1250
+ raise e
1261
1251
 
1262
1252
  # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
1263
1253
  @GeneralUtilities.check_arguments
1264
- 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) -> tuple[int, str, str, int]:
1265
- return self.run_program_argsasarray(program, GeneralUtilities.arguments_to_array(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)
1254
+ 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) -> tuple[int, str, str, int]:
1255
+ return self.run_program_argsasarray(program, GeneralUtilities.arguments_to_array(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)
1266
1256
 
1267
1257
  # Return-values program_runner: Pid
1268
1258
  @GeneralUtilities.check_arguments
1269
- def run_program_argsasarray_async(self, program: str, arguments_as_array: list[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, custom_argument: object = None) -> int:
1259
+ def run_program_argsasarray_async(self, program: str, arguments_as_array: list[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, custom_argument: object = None) -> int:
1270
1260
  mock_loader_result = self.__try_load_mock(program, ' '.join(arguments_as_array), working_directory)
1271
1261
  if mock_loader_result[0]:
1272
1262
  return mock_loader_result[1]
1273
1263
 
1274
- process: Popen = 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)
1264
+ process: Popen = 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)
1275
1265
  return process.pid
1276
1266
 
1277
1267
  # Return-values program_runner: Pid
1278
1268
  @GeneralUtilities.check_arguments
1279
1269
  def run_program_async(self, program: str, arguments: str = "", working_directory: str = None, verbosity: int = 1,
1280
- 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, custom_argument: object = None) -> int:
1281
- return self.run_program_argsasarray_async(program, GeneralUtilities.arguments_to_array(arguments), working_directory, verbosity, print_errors_as_information, log_file, timeoutInSeconds, addLogOverhead, title, log_namespace, arguments_for_log, custom_argument)
1270
+ 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, custom_argument: object = None) -> int:
1271
+ return self.run_program_argsasarray_async(program, GeneralUtilities.arguments_to_array(arguments), working_directory, verbosity, print_errors_as_information, log_file, timeoutInSeconds, addLogOverhead, title, log_namespace, arguments_for_log, custom_argument)
1282
1272
 
1283
1273
  @GeneralUtilities.check_arguments
1284
1274
  def __try_load_mock(self, program: str, arguments: str, working_directory: str) -> tuple[bool, tuple[int, str, str, int]]:
@@ -1297,28 +1287,6 @@ class ScriptCollectionCore:
1297
1287
  else:
1298
1288
  return GeneralUtilities.resolve_relative_path_from_current_working_directory(workingdirectory)
1299
1289
 
1300
- @GeneralUtilities.check_arguments
1301
- def __write_error_output(self, print_errors_as_information: bool, stderr: str):
1302
- if print_errors_as_information:
1303
- GeneralUtilities.write_message_to_stdout(stderr)
1304
- else:
1305
- GeneralUtilities.write_message_to_stderr(stderr)
1306
-
1307
- @GeneralUtilities.check_arguments
1308
- def __format_program_execution_information(self, exitcode: int = None, stdout: str = None, stderr: str = None, program: str = None, argument: str = None, workingdirectory: str = None, title: str = None, pid: int = None, execution_duration: timedelta = None):
1309
- result = ""
1310
- if (exitcode is not None and stdout is not None and stderr is not None):
1311
- result = f"{result} Exitcode: {exitcode}; StdOut: '{stdout}'; StdErr: '{stderr}'"
1312
- if (pid is not None):
1313
- result = f"Pid: '{pid}'; {result}"
1314
- if (program is not None and argument is not None and workingdirectory is not None):
1315
- result = f"Command: '{workingdirectory}> {program} {argument}'; {result}"
1316
- if (execution_duration is not None):
1317
- result = f"{result}; Duration: '{str(execution_duration)}'"
1318
- if (title is not None):
1319
- result = f"Title: '{title}'; {result}"
1320
- return result.strip()
1321
-
1322
1290
  @GeneralUtilities.check_arguments
1323
1291
  def verify_no_pending_mock_program_calls(self):
1324
1292
  if (len(self.__mocked_program_calls) > 0):
@@ -1451,8 +1419,8 @@ class ScriptCollectionCore:
1451
1419
  @GeneralUtilities.check_arguments
1452
1420
  def get_version_from_gitversion(self, folder: str, variable: str) -> str:
1453
1421
  # called twice as workaround for issue 1877 in gitversion ( https://github.com/GitTools/GitVersion/issues/1877 )
1454
- result = self.run_program_argsasarray("gitversion", ["/showVariable", variable], folder)
1455
- result = self.run_program_argsasarray("gitversion", ["/showVariable", variable], folder)
1422
+ result = self.run_program_argsasarray("gitversion", ["/showVariable", variable], folder,verbosity=0)
1423
+ result = self.run_program_argsasarray("gitversion", ["/showVariable", variable], folder,verbosity=0)
1456
1424
  result = GeneralUtilities.strip_new_line_character(result[1])
1457
1425
 
1458
1426
  return result
@@ -21,7 +21,6 @@ from .GeneralUtilities import GeneralUtilities
21
21
  from .ScriptCollectionCore import ScriptCollectionCore
22
22
  from .ProgramRunnerEpew import ProgramRunnerEpew
23
23
 
24
-
25
24
  class CreateReleaseConfiguration():
26
25
  projectname: str
27
26
  remotename: str
@@ -146,27 +145,27 @@ class TasksForCommonProjectStructure:
146
145
  @GeneralUtilities.check_arguments
147
146
  def get_testcoverage_threshold_from_codeunit_file(self, codeunit_file: str):
148
147
  root: etree._ElementTree = etree.parse(codeunit_file)
149
- return float(str(root.xpath('//cps:properties/cps:testsettings/@minimalcodecoverageinpercent', namespaces={ 'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure' })[0]))
148
+ return float(str(root.xpath('//cps:properties/cps:testsettings/@minimalcodecoverageinpercent', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0]))
150
149
 
151
150
  @GeneralUtilities.check_arguments
152
151
  def codeunit_has_testable_sourcecode(self, codeunit_file: str) -> bool:
153
152
  root: etree._ElementTree = etree.parse(codeunit_file)
154
- return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@codeunithastestablesourcecode', namespaces={ 'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure' })[0]))
153
+ return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@codeunithastestablesourcecode', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0]))
155
154
 
156
155
  @GeneralUtilities.check_arguments
157
156
  def codeunit_throws_exception_if_codeunitfile_is_not_validatable(self, codeunit_file: str) -> bool:
158
157
  root: etree._ElementTree = etree.parse(codeunit_file)
159
- return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@throwexceptionifcodeunitfilecannotbevalidated', namespaces={ 'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure' })[0]))
158
+ return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@throwexceptionifcodeunitfilecannotbevalidated', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0]))
160
159
 
161
160
  @GeneralUtilities.check_arguments
162
161
  def codeunit_has_updatable_dependencies(self, codeunit_file: str) -> bool:
163
162
  root: etree._ElementTree = etree.parse(codeunit_file)
164
- return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@codeunithasupdatabledependencies', namespaces={ 'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure' })[0]))
163
+ return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@codeunithasupdatabledependencies', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0]))
165
164
 
166
165
  @GeneralUtilities.check_arguments
167
166
  def get_codeunit_description(self, codeunit_file: str) -> bool:
168
167
  root: etree._ElementTree = etree.parse(codeunit_file)
169
- return str(root.xpath('//cps:properties/@description', namespaces={ 'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure' })[0])
168
+ return str(root.xpath('//cps:properties/@description', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0])
170
169
 
171
170
  @GeneralUtilities.check_arguments
172
171
  def check_testcoverage(self, testcoverage_file_in_cobertura_format: str, repository_folder: str, codeunitname: str) -> None:
@@ -194,7 +193,7 @@ class TasksForCommonProjectStructure:
194
193
  verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
195
194
  repository_folder: str = str(Path(os.path.dirname(run_testcases_file)).parent.parent.parent.absolute())
196
195
  codeunit_folder = os.path.join(repository_folder, codeunitname)
197
- self.__sc.run_program("coverage", f"run -m pytest ./{codeunitname}Tests", codeunit_folder, verbosity=verbosity)
196
+ self.__sc.run_program("coverage", f"run -m pytest -s ./{codeunitname}Tests", codeunit_folder, verbosity=verbosity)
198
197
  self.__sc.run_program("coverage", "xml", codeunit_folder, verbosity=verbosity)
199
198
  coveragefolder = os.path.join(repository_folder, codeunitname, "Other/Artifacts/TestCoverage")
200
199
  GeneralUtilities.ensure_directory_exists(coveragefolder)
@@ -227,11 +226,11 @@ class TasksForCommonProjectStructure:
227
226
  codeunit_name = os.path.basename(codeunit_folder)
228
227
  src_folder = GeneralUtilities.resolve_relative_path(package_name, codeunit_folder) # TODO replace packagename
229
228
  artifacts_folder = os.path.join(codeunit_folder, "Other", "Artifacts")
230
- verbosity=self.get_verbosity_from_commandline_arguments(args,verbosity)
229
+ verbosity = self.get_verbosity_from_commandline_arguments(args, verbosity)
231
230
  for target in targets:
232
231
  GeneralUtilities.write_message_to_stdout(f"Build package {package_name} for target {target}...")
233
- sc=ScriptCollectionCore()
234
- sc.program_runner=ProgramRunnerEpew()
232
+ sc = ScriptCollectionCore()
233
+ sc.program_runner = ProgramRunnerEpew()
235
234
  sc.run_program("flutter", f"build {target}", src_folder, verbosity)
236
235
  if target == "web":
237
236
  web_relase_folder = os.path.join(src_folder, "build/web")
@@ -291,11 +290,11 @@ class TasksForCommonProjectStructure:
291
290
  GeneralUtilities.ensure_directory_exists(bom_folder_full)
292
291
  if not os.path.isfile(os.path.join(codeunit_folder, "requirements.txt")):
293
292
  raise ValueError(f"Codeunit {codeunitname} does not have a 'requirements.txt'-file.")
294
- #TODO check that all values from setup.cfg are contained in requirements.txt
295
- result=self.__sc.run_program("cyclonedx-py", "requirements", codeunit_folder, verbosity=verbosity)
296
- bom_file=os.path.join(codeunit_folder, f"{bom_folder}/{codeunitname}.{codeunitversion}.bom.json")
293
+ # TODO check that all values from setup.cfg are contained in requirements.txt
294
+ result = self.__sc.run_program("cyclonedx-py", "requirements", codeunit_folder, verbosity=verbosity)
295
+ bom_file = os.path.join(codeunit_folder, f"{bom_folder}/{codeunitname}.{codeunitversion}.bom.json")
297
296
  GeneralUtilities.ensure_file_exists(bom_file)
298
- GeneralUtilities.write_text_to_file(bom_file,result[1])
297
+ GeneralUtilities.write_text_to_file(bom_file, result[1])
299
298
 
300
299
  @GeneralUtilities.check_arguments
301
300
  def standardized_tasks_push_wheel_file_to_registry(self, wheel_file: str, api_key: str, repository: str, gpg_identity: str, verbosity: int) -> None:
@@ -415,14 +414,14 @@ class TasksForCommonProjectStructure:
415
414
  @GeneralUtilities.check_arguments
416
415
  def get_property_from_commandline_arguments(commandline_arguments: list[str], property_name: str) -> str:
417
416
  result: str = None
418
- count=len(commandline_arguments)
419
- loop_index=-1
417
+ count = len(commandline_arguments)
418
+ loop_index = -1
420
419
  for commandline_argument in commandline_arguments:
421
- loop_index=loop_index+1
422
- if loop_index<count-1:
420
+ loop_index = loop_index+1
421
+ if loop_index < count-1:
423
422
  prefix = f"--overwrite_{property_name}"
424
- if commandline_argument==prefix:
425
- result= commandline_arguments[loop_index+1]
423
+ if commandline_argument == prefix:
424
+ result = commandline_arguments[loop_index+1]
426
425
  return result
427
426
  return result
428
427
 
@@ -641,15 +640,15 @@ class TasksForCommonProjectStructure:
641
640
  license_file = os.path.join(repository_folder, "License.txt")
642
641
  target = os.path.join(outputfolder, f"{codeunit_name}.License.txt")
643
642
  shutil.copyfile(license_file, target)
644
- if 0<len(files_to_sign):
643
+ if 0 < len(files_to_sign):
645
644
  for key, value in files_to_sign.items():
646
- dll_file=key
647
- snk_file=value
648
- dll_file_full=os.path.join(outputfolder,dll_file)
645
+ dll_file = key
646
+ snk_file = value
647
+ dll_file_full = os.path.join(outputfolder, dll_file)
649
648
  if os.path.isfile(dll_file_full):
650
- GeneralUtilities.assert_condition(self.__sc.run_program("sn",f"-vf {dll_file}", outputfolder,throw_exception_if_exitcode_is_not_zero=False)[0]==1, f"Pre-verifying of {dll_file} failed.")
651
- self.__sc.run_program("sn",f"-R {dll_file} {snk_file}", outputfolder)
652
- GeneralUtilities.assert_condition(self.__sc.run_program("sn",f"-vf {dll_file}", outputfolder,throw_exception_if_exitcode_is_not_zero=False)[0]==0, f"Verifying of {dll_file} failed.")
649
+ GeneralUtilities.assert_condition(self.__sc.run_program("sn", f"-vf {dll_file}", outputfolder, throw_exception_if_exitcode_is_not_zero=False)[0] == 1, f"Pre-verifying of {dll_file} failed.")
650
+ self.__sc.run_program("sn", f"-R {dll_file} {snk_file}", outputfolder)
651
+ GeneralUtilities.assert_condition(self.__sc.run_program("sn", f"-vf {dll_file}", outputfolder, throw_exception_if_exitcode_is_not_zero=False)[0] == 0, f"Verifying of {dll_file} failed.")
653
652
  sarif_filename = f"{csproj_file_name_without_extension}.sarif"
654
653
  sarif_source_file = os.path.join(sarif_folder, sarif_filename)
655
654
  if os.path.exists(sarif_source_file):
@@ -787,9 +786,9 @@ class TasksForCommonProjectStructure:
787
786
  history_folder_full = os.path.join(repository_folder, history_folder)
788
787
  GeneralUtilities.ensure_directory_exists(history_folder_full)
789
788
  history_argument = f" -historydir:{history_folder}"
790
- argument=(f"-reports:{codeunitname}/Other/Artifacts/TestCoverage/TestCoverage.xml " +
791
- f"-targetdir:{codeunitname}/Other/Artifacts/TestCoverageReport --verbosity:{verbose_argument_for_reportgenerator}{history_argument} " +
792
- f"-title:{codeunitname} -tag:v{codeunit_version}")
789
+ argument = (f"-reports:{codeunitname}/Other/Artifacts/TestCoverage/TestCoverage.xml " +
790
+ f"-targetdir:{codeunitname}/Other/Artifacts/TestCoverageReport --verbosity:{verbose_argument_for_reportgenerator}{history_argument} " +
791
+ f"-title:{codeunitname} -tag:v{codeunit_version}")
793
792
  self.__sc.run_program("reportgenerator", argument,
794
793
  repository_folder, verbosity=verbosity)
795
794
  if not add_testcoverage_history_entry:
@@ -806,13 +805,12 @@ class TasksForCommonProjectStructure:
806
805
  f"--verbosity:{verbose_argument_for_reportgenerator}", os.path.join(repository_folder, codeunitname),
807
806
  verbosity=verbosity)
808
807
 
809
-
810
808
  @GeneralUtilities.check_arguments
811
809
  def standardized_tasks_run_testcases_for_dotnet_project(self, runtestcases_file: str, targetenvironmenttype: str, verbosity: int, generate_badges: bool, target_environmenttype_mapping: dict[str, str], commandline_arguments: list[str]) -> None:
812
810
  dotnet_build_configuration: str = target_environmenttype_mapping[targetenvironmenttype]
813
811
  codeunit_name: str = os.path.basename(str(Path(os.path.dirname(runtestcases_file)).parent.parent.absolute()))
814
812
  verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
815
- repository_folder: str = str(Path(os.path.dirname(runtestcases_file)).parent.parent.parent.absolute()).replace("\\","/")
813
+ repository_folder: str = str(Path(os.path.dirname(runtestcases_file)).parent.parent.parent.absolute()).replace("\\", "/")
816
814
  coverage_file_folder = os.path.join(repository_folder, codeunit_name, "Other/Artifacts/TestCoverage")
817
815
  temp_folder = os.path.join(tempfile.gettempdir(), str(uuid.uuid4()))
818
816
  GeneralUtilities.ensure_directory_exists(temp_folder)
@@ -828,11 +826,11 @@ class TasksForCommonProjectStructure:
828
826
  os.rename(os.path.join(coverage_file_folder, "Testcoverage.cobertura.xml"), target_file)
829
827
  self.__remove_unrelated_package_from_testcoverage_file(target_file, codeunit_name)
830
828
  root: etree._ElementTree = etree.parse(target_file)
831
- source_base_path_in_coverage_file :str= root.xpath("//coverage/sources/source/text()")[0].replace("\\","/")
832
- content=GeneralUtilities.read_text_from_file(target_file)
829
+ source_base_path_in_coverage_file: str = root.xpath("//coverage/sources/source/text()")[0].replace("\\", "/")
830
+ content = GeneralUtilities.read_text_from_file(target_file)
833
831
  GeneralUtilities.assert_condition(source_base_path_in_coverage_file.startswith(repository_folder) or repository_folder.startswith(source_base_path_in_coverage_file), f"Unexpected path for coverage. Sourcepath: \"{source_base_path_in_coverage_file}\"; repository: \"{repository_folder}\"")
834
832
  content = re.sub('\\\\', '/', content)
835
- content= re.sub("filename=\"([^\"]+)\"",lambda match: self.__standardized_tasks_run_testcases_for_dotnet_project_helper(source_base_path_in_coverage_file,codeunit_folder,match), content)
833
+ content = re.sub("filename=\"([^\"]+)\"", lambda match: self.__standardized_tasks_run_testcases_for_dotnet_project_helper(source_base_path_in_coverage_file, codeunit_folder, match), content)
836
834
  GeneralUtilities.write_text_to_file(target_file, content)
837
835
  self.run_testcases_common_post_task(repository_folder, codeunit_name, verbosity, generate_badges, targetenvironmenttype, commandline_arguments)
838
836
 
@@ -852,34 +850,34 @@ class TasksForCommonProjectStructure:
852
850
  filename = "TestCoverage.xml"
853
851
  full_file = os.path.join(folder, filename)
854
852
  GeneralUtilities.write_text_to_file(full_file, re.sub("<source>.+<\\/source>", f"<source><!--[repository]/-->./{codeunitname}/</source>", GeneralUtilities.read_text_from_file(full_file)))
855
- TasksForCommonProjectStructure.__remove_not_existing_files_from_testcoverage_file(full_file,repository_folder, codeunitname)
853
+ TasksForCommonProjectStructure.__remove_not_existing_files_from_testcoverage_file(full_file, repository_folder, codeunitname)
856
854
 
857
855
  @GeneralUtilities.check_arguments
858
- def __standardized_tasks_run_testcases_for_dotnet_project_helper(self,source:str,codeunit_folder:str,match:re.Match)->str:
859
- filename=match.group(1)
860
- file=os.path.join(source,filename)
861
- #GeneralUtilities.assert_condition(os.path.isfile(file),f"File \"{file}\" does not exist.")
856
+ def __standardized_tasks_run_testcases_for_dotnet_project_helper(self, source: str, codeunit_folder: str, match: re.Match) -> str:
857
+ filename = match.group(1)
858
+ file = os.path.join(source, filename)
859
+ # GeneralUtilities.assert_condition(os.path.isfile(file),f"File \"{file}\" does not exist.")
862
860
  GeneralUtilities.assert_condition(file.startswith(codeunit_folder),
863
- f"Unexpected path for coverage-file. File: \"{file}\"; codeunitfolder: \"{codeunit_folder}\"")
864
- filename_relative= f".{file[len(codeunit_folder):]}"
861
+ f"Unexpected path for coverage-file. File: \"{file}\"; codeunitfolder: \"{codeunit_folder}\"")
862
+ filename_relative = f".{file[len(codeunit_folder):]}"
865
863
  return f'filename="{filename_relative}"'
866
864
 
867
865
  @staticmethod
868
866
  @GeneralUtilities.check_arguments
869
- def __remove_not_existing_files_from_testcoverage_file(testcoveragefile: str,repository_folder:str, codeunit_name: str) -> None:
867
+ def __remove_not_existing_files_from_testcoverage_file(testcoveragefile: str, repository_folder: str, codeunit_name: str) -> None:
870
868
  root: etree._ElementTree = etree.parse(testcoveragefile)
871
- codeunit_folder=os.path.join(repository_folder,codeunit_name)
872
- xpath=f"//coverage/packages/package[@name='{codeunit_name}']/classes/class"
869
+ codeunit_folder = os.path.join(repository_folder, codeunit_name)
870
+ xpath = f"//coverage/packages/package[@name='{codeunit_name}']/classes/class"
873
871
  classes = root.xpath(xpath)
874
- found_existing_files=False
872
+ found_existing_files = False
875
873
  for clas in classes:
876
- filename=clas.attrib['filename']
877
- file=os.path.join(codeunit_folder,filename)
874
+ filename = clas.attrib['filename']
875
+ file = os.path.join(codeunit_folder, filename)
878
876
  if os.path.isfile(file):
879
- found_existing_files=True
877
+ found_existing_files = True
880
878
  else:
881
879
  clas.getparent().remove(clas)
882
- GeneralUtilities.assert_condition(found_existing_files,f"No existing files in testcoderage-report-file \"{testcoveragefile}\".")
880
+ GeneralUtilities.assert_condition(found_existing_files, f"No existing files in testcoderage-report-file \"{testcoveragefile}\".")
883
881
  result = etree.tostring(root).decode("utf-8")
884
882
  GeneralUtilities.write_text_to_file(testcoveragefile, result)
885
883
 
@@ -1151,7 +1149,7 @@ class TasksForCommonProjectStructure:
1151
1149
  @GeneralUtilities.check_arguments
1152
1150
  def codeunit_is_enabled(self, codeunit_file: str) -> bool:
1153
1151
  root: etree._ElementTree = etree.parse(codeunit_file)
1154
- return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:codeunit/@enabled', namespaces={ 'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure' })[0]))
1152
+ return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:codeunit/@enabled', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0]))
1155
1153
 
1156
1154
  @GeneralUtilities.check_arguments
1157
1155
  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:
@@ -1161,7 +1159,7 @@ class TasksForCommonProjectStructure:
1161
1159
 
1162
1160
  src_branch_commit_id = self.__sc.git_get_commit_id(repository_folder, source_branch)
1163
1161
  if (src_branch_commit_id == self.__sc.git_get_commit_id(repository_folder, target_branch)):
1164
- 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})")
1162
+ 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})")
1165
1163
 
1166
1164
  self.__sc.git_checkout(repository_folder, source_branch)
1167
1165
  self.build_codeunits(repository_folder, verbosity, "QualityCheck", additional_arguments_file, True, None)
@@ -1278,9 +1276,9 @@ class TasksForCommonProjectStructure:
1278
1276
  @GeneralUtilities.check_arguments
1279
1277
  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:
1280
1278
  folder_of_this_file = os.path.dirname(push_artifacts_file)
1281
- filename=os.path.basename(push_artifacts_file)
1282
- codeunitname_regex:str="([a-zA-Z0-9]+)"
1283
- filename_regex:str=f"PushArtifacts\\.{codeunitname_regex}\\.py"
1279
+ filename = os.path.basename(push_artifacts_file)
1280
+ codeunitname_regex: str = "([a-zA-Z0-9]+)"
1281
+ filename_regex: str = f"PushArtifacts\\.{codeunitname_regex}\\.py"
1284
1282
  if match := re.search(filename_regex, filename, re.IGNORECASE):
1285
1283
  codeunitname = match.group(1)
1286
1284
  else:
@@ -1312,11 +1310,11 @@ class TasksForCommonProjectStructure:
1312
1310
  @GeneralUtilities.check_arguments
1313
1311
  def get_dependent_code_units(self, codeunit_file: str) -> set[str]:
1314
1312
  root: etree._ElementTree = etree.parse(codeunit_file)
1315
- return set(root.xpath('//cps:dependentcodeunit/text()', namespaces={ 'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure' }))
1313
+ return set(root.xpath('//cps:dependentcodeunit/text()', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'}))
1316
1314
 
1317
1315
  @GeneralUtilities.check_arguments
1318
- def dependent_codeunit_exists(self, repository:str,codeunit:str) -> None:
1319
- codeunit_file=f"{repository}/{codeunit}/{codeunit}.codeunit.xml"
1316
+ def dependent_codeunit_exists(self, repository: str, codeunit: str) -> None:
1317
+ codeunit_file = f"{repository}/{codeunit}/{codeunit}.codeunit.xml"
1320
1318
  return os.path.isfile(codeunit_file)
1321
1319
 
1322
1320
  @GeneralUtilities.check_arguments
@@ -1411,7 +1409,7 @@ class TasksForCommonProjectStructure:
1411
1409
  actual_author_formatted = f"{actual_author[0]} <{actual_author[1]}>"
1412
1410
  raise ValueError(f'Author/Comitter "{actual_author_formatted}" is not in the codeunit-developer-team. If {actual_author} is a authorized developer for this codeunit you should consider defining this in the codeunit-file or adapting the name using a .mailmap-file (see https://git-scm.com/docs/gitmailmap). The developer-team-check can also be disabled using the property validate_developers_of_repository.')
1413
1411
 
1414
- dependent_codeunits=self.get_dependent_code_units(codeunit_file)
1412
+ dependent_codeunits = self.get_dependent_code_units(codeunit_file)
1415
1413
  for dependent_codeunit in dependent_codeunits:
1416
1414
  if not self.dependent_codeunit_exists(repository_folder, dependent_codeunit):
1417
1415
  raise ValueError(f"Codeunit {codeunit_name} does have dependent codeunit {dependent_codeunit} which does not exist.")
@@ -1467,7 +1465,7 @@ class TasksForCommonProjectStructure:
1467
1465
  src_prefix = latest_tag
1468
1466
  dst = "HEAD"
1469
1467
  dst_prefix = f"v{current_version}"
1470
- self.__sc.run_program_argsasarray( "sh", ['-c', f'git diff --src-prefix={src_prefix}/ --dst-prefix={dst_prefix}/ {src} {dst} -- {codeunit_name} | pygmentize -l diff -f html -O full -o {target_file} -P style=github-dark'], repository_folder)
1468
+ self.__sc.run_program_argsasarray("sh", ['-c', f'git diff --src-prefix={src_prefix}/ --dst-prefix={dst_prefix}/ {src} {dst} -- {codeunit_name} | pygmentize -l diff -f html -O full -o {target_file} -P style=github-dark'], repository_folder)
1471
1469
 
1472
1470
  @GeneralUtilities.check_arguments
1473
1471
  def get_version_of_project(self, repository_folder: str) -> str:
@@ -1504,36 +1502,36 @@ class TasksForCommonProjectStructure:
1504
1502
  # TODO check if there are errors in sarif-file
1505
1503
 
1506
1504
  @GeneralUtilities.check_arguments
1507
- def standardized_tasks_run_testcases_for_flutter_project_in_common_project_structure(self, script_file: str, verbosity: int, args: list[str], package_name: str,build_environment_target_type: str, generate_badges: bool):
1505
+ def standardized_tasks_run_testcases_for_flutter_project_in_common_project_structure(self, script_file: str, verbosity: int, args: list[str], package_name: str, build_environment_target_type: str, generate_badges: bool):
1508
1506
  codeunit_folder = GeneralUtilities.resolve_relative_path("../../..", script_file)
1509
1507
  repository_folder = GeneralUtilities.resolve_relative_path("..", codeunit_folder)
1510
- codeunit_name=os.path.basename(codeunit_folder)
1508
+ codeunit_name = os.path.basename(codeunit_folder)
1511
1509
  src_folder = GeneralUtilities.resolve_relative_path(package_name, codeunit_folder)
1512
- verbosity=self.get_verbosity_from_commandline_arguments(args,verbosity)
1513
- sc=ScriptCollectionCore()
1514
- sc.program_runner=ProgramRunnerEpew()
1510
+ verbosity = self.get_verbosity_from_commandline_arguments(args, verbosity)
1511
+ sc = ScriptCollectionCore()
1512
+ sc.program_runner = ProgramRunnerEpew()
1515
1513
  sc.run_program("flutter", "test --coverage", src_folder, verbosity)
1516
- test_coverage_folder_relative="Other/Artifacts/TestCoverage"
1517
- test_coverage_folder=GeneralUtilities.resolve_relative_path(test_coverage_folder_relative, codeunit_folder)
1514
+ test_coverage_folder_relative = "Other/Artifacts/TestCoverage"
1515
+ test_coverage_folder = GeneralUtilities.resolve_relative_path(test_coverage_folder_relative, codeunit_folder)
1518
1516
  GeneralUtilities.ensure_directory_exists(test_coverage_folder)
1519
- coverage_file_relative=f"{test_coverage_folder_relative}/TestCoverage.xml"
1520
- coverage_file=GeneralUtilities.resolve_relative_path(coverage_file_relative, codeunit_folder)
1517
+ coverage_file_relative = f"{test_coverage_folder_relative}/TestCoverage.xml"
1518
+ coverage_file = GeneralUtilities.resolve_relative_path(coverage_file_relative, codeunit_folder)
1521
1519
  sc.run_program("lcov_cobertura", f"coverage/lcov.info --base-dir . --excludes test --output ../{coverage_file_relative} --demangle", src_folder, verbosity)
1522
- content=GeneralUtilities.read_text_from_file(coverage_file)
1520
+ content = GeneralUtilities.read_text_from_file(coverage_file)
1523
1521
  content = re.sub('<![^<]+>', '', content)
1524
1522
  content = re.sub('\\\\', '/', content)
1525
1523
  content = re.sub('\\ name=\\"lib\\"', '', content)
1526
1524
  content = re.sub('<package ', f'<package name="{codeunit_name}" ', content)
1527
1525
  content = re.sub('\\ filename=\\"lib/', f' filename="{package_name}/lib/', content)
1528
- GeneralUtilities.write_text_to_file(coverage_file,content)
1529
- self.run_testcases_common_post_task(repository_folder,codeunit_name,verbosity,generate_badges,build_environment_target_type,args)
1526
+ GeneralUtilities.write_text_to_file(coverage_file, content)
1527
+ self.run_testcases_common_post_task(repository_folder, codeunit_name, verbosity, generate_badges, build_environment_target_type, args)
1530
1528
 
1531
1529
  @GeneralUtilities.check_arguments
1532
1530
  def standardized_tasks_run_testcases_for_angular_codeunit(self, runtestcases_script_file: str, build_environment_target_type: str, generate_badges: bool, verbosity: int, commandline_arguments: list[str]) -> None:
1533
1531
  codeunit_name: str = os.path.basename(str(Path(os.path.dirname(runtestcases_script_file)).parent.parent.absolute()))
1534
1532
  verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
1535
1533
  codeunit_folder = GeneralUtilities.resolve_relative_path("../..", os.path.dirname(runtestcases_script_file))
1536
- repository_folder=os.path.dirname(codeunit_folder)
1534
+ repository_folder = os.path.dirname(codeunit_folder)
1537
1535
  self.run_with_epew(
1538
1536
  "ng", "test --watch=false --browsers ChromeHeadless --code-coverage", codeunit_folder, verbosity=verbosity)
1539
1537
  coverage_folder = os.path.join(codeunit_folder, "Other", "Artifacts", "TestCoverage")
@@ -1541,7 +1539,7 @@ class TasksForCommonProjectStructure:
1541
1539
  GeneralUtilities.ensure_file_does_not_exist(target_file)
1542
1540
  os.rename(os.path.join(coverage_folder, "cobertura-coverage.xml"), target_file)
1543
1541
  self.__rename_packagename_in_coverage_file(target_file, codeunit_name)
1544
- content=GeneralUtilities.read_text_from_file(target_file)
1542
+ content = GeneralUtilities.read_text_from_file(target_file)
1545
1543
  content = re.sub('\\\\', '/', content)
1546
1544
  self.run_testcases_common_post_task(repository_folder, codeunit_name, verbosity, generate_badges, build_environment_target_type, commandline_arguments)
1547
1545
 
@@ -1596,7 +1594,7 @@ class TasksForCommonProjectStructure:
1596
1594
  @GeneralUtilities.check_arguments
1597
1595
  def set_constant_for_codeunitmajorversion(self, codeunit_folder: str) -> None:
1598
1596
  codeunit_version: str = self.get_version_of_codeunit_folder(codeunit_folder)
1599
- major_version=int(codeunit_version.split(".")[0])
1597
+ major_version = int(codeunit_version.split(".")[0])
1600
1598
  self.set_constant(codeunit_folder, "CodeUnitMajorVersion", str(major_version))
1601
1599
 
1602
1600
  @GeneralUtilities.check_arguments
@@ -1774,8 +1772,8 @@ class TasksForCommonProjectStructure:
1774
1772
  shutil.copytree(artifacts_folder, target_folder)
1775
1773
 
1776
1774
  @GeneralUtilities.check_arguments
1777
- def add_github_release(self, productname: str, projectversion: str, build_artifacts_folder: str, github_username: str, repository_folder: str, verbosity: int, commandline_arguments: list[str]) -> None:
1778
- verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
1775
+ def add_github_release(self, productname: str, projectversion: str, build_artifacts_folder: str, github_username: str, repository_folder: str, commandline_arguments: list[str]) -> None:
1776
+ verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, 1)
1779
1777
  github_repo = f"{github_username}/{productname}"
1780
1778
  artifact_files = []
1781
1779
  codeunits = self.get_codeunits(repository_folder)
@@ -1807,7 +1805,7 @@ class TasksForCommonProjectStructure:
1807
1805
  codeunit_name = os.path.basename(codeunit_folder)
1808
1806
 
1809
1807
  build_folder = os.path.join(codeunit_folder, "Other", "Build")
1810
- self.__sc.run_program("python", "Build.py", build_folder)
1808
+ self.__sc.run_program("python", "Build.py", build_folder, verbosity)
1811
1809
 
1812
1810
  csproj_file = os.path.join(codeunit_folder, codeunit_name, f"{codeunit_name}.csproj")
1813
1811
  self.__sc.update_dependencies_of_dotnet_project(csproj_file, verbosity)
@@ -1819,11 +1817,11 @@ class TasksForCommonProjectStructure:
1819
1817
  pass # TODO generalize and add option to ignore certain dependencies
1820
1818
 
1821
1819
  @GeneralUtilities.check_arguments
1822
- def run_local_test_service(self, file:str):
1823
- example_folder=os.path.dirname(file)
1824
- example_name=os.path.basename(example_folder)
1825
- title=f"Test{example_name}"
1826
- self.__sc.run_program("docker",f"compose -p {title.lower()} up",example_folder,title=title)
1820
+ def run_local_test_service(self, file: str):
1821
+ example_folder = os.path.dirname(file)
1822
+ example_name = os.path.basename(example_folder)
1823
+ title = f"Test{example_name}"
1824
+ self.__sc.run_program("docker", f"compose -p {title.lower()} up", example_folder, title=title)
1827
1825
 
1828
1826
  @GeneralUtilities.check_arguments
1829
1827
  def standardized_tasks_update_version_in_docker_examples(self, file, codeunit_version) -> None:
@@ -1850,9 +1848,9 @@ class TasksForCommonProjectStructure:
1850
1848
  image_filename = os.path.basename(sc.find_file_by_extension(oci_image_artifacts_folder, "tar"))
1851
1849
  codeunit_name = os.path.basename(GeneralUtilities.resolve_relative_path("../../../../..", folder))
1852
1850
  if remove_old_container:
1853
- docker_compose_file=f"{folder}/docker-compose.yml"
1854
- container_names=[]
1855
- lines=GeneralUtilities.read_lines_from_file(docker_compose_file)
1851
+ docker_compose_file = f"{folder}/docker-compose.yml"
1852
+ container_names = []
1853
+ lines = GeneralUtilities.read_lines_from_file(docker_compose_file)
1856
1854
  for line in lines:
1857
1855
  if match := re.search("container_name:\\s*'?([^']+)'?", line):
1858
1856
  container_names.append(match.group(1))
@@ -1873,7 +1871,6 @@ class TasksForCommonProjectStructure:
1873
1871
  GeneralUtilities.write_message_to_stdout("Start docker-container...")
1874
1872
  sc_epew.run_program("docker", f"compose --project-name {docker_project_name} up --abort-on-container-exit", folder, verbosity=verbosity)
1875
1873
 
1876
-
1877
1874
  @GeneralUtilities.check_arguments
1878
1875
  def create_artifact_for_development_certificate(self, codeunit_folder: str):
1879
1876
  ce_source_folder = GeneralUtilities.resolve_relative_path("Other/Resources/DevelopmentCertificate", codeunit_folder)
@@ -1894,6 +1891,18 @@ class TasksForCommonProjectStructure:
1894
1891
  result.append(str(item))
1895
1892
  return result
1896
1893
 
1894
+ @GeneralUtilities.check_arguments
1895
+ def get_project_name(self, repository_folder: str) -> str:
1896
+ for file in GeneralUtilities.get_direct_files_of_folder(repository_folder):
1897
+ if file.endswith(".code-workspace"):
1898
+ return Path(file).stem
1899
+ raise ValueError(f'Project-name can not be calculated for repository "{repository_folder}"')
1900
+
1901
+ def __check_target_environmenttype(self, target_environmenttype: str):
1902
+ allowed_values = list(self.get_default_target_environmenttype_mapping().values())
1903
+ if not (target_environmenttype in allowed_values):
1904
+ raise ValueError(f"Invalid target-environmenttype: '{target_environmenttype}'")
1905
+
1897
1906
  @GeneralUtilities.check_arguments
1898
1907
  def build_codeunit(self, codeunit_folder: str, verbosity: int = 1, target_environmenttype: str = "QualityCheck",
1899
1908
  additional_arguments_file: str = None, is_pre_merge: bool = False, export_target_directory: str = None,
@@ -1905,7 +1914,7 @@ class TasksForCommonProjectStructure:
1905
1914
  is_pre_merge, export_target_directory, assume_dependent_codeunits_are_already_built)
1906
1915
 
1907
1916
  @GeneralUtilities.check_arguments
1908
- def build_codeunitsC(self, repository_folder: str, image:str, verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None) -> None:
1917
+ def build_codeunitsC(self, repository_folder: str, image: str, verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None) -> None:
1909
1918
  if target_environmenttype == "Development":
1910
1919
  raise ValueError(f"build_codeunitsC is not available for target_environmenttype {target_environmenttype}.")
1911
1920
  # TODO handle additional_arguments_file
@@ -1918,19 +1927,14 @@ class TasksForCommonProjectStructure:
1918
1927
 
1919
1928
  @GeneralUtilities.check_arguments
1920
1929
  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) -> None:
1930
+ self.__check_target_environmenttype(target_environmenttype)
1921
1931
  repository_folder = GeneralUtilities.resolve_relative_path_from_current_working_directory(repository_folder)
1922
1932
  codeunits = self.get_codeunits(repository_folder, False)
1923
1933
  self.build_specific_codeunits(repository_folder, codeunits, verbosity, target_environmenttype, additional_arguments_file, is_pre_merge, export_target_directory)
1924
1934
 
1925
- @GeneralUtilities.check_arguments
1926
- def get_project_name(self, repository_folder:str) -> str:
1927
- for file in GeneralUtilities.get_direct_files_of_folder(repository_folder):
1928
- if file.endswith(".code-workspace"):
1929
- return Path(file).stem
1930
- raise ValueError(f'Project-name can not be calculated for repository "{repository_folder}"')
1931
-
1932
1935
  @GeneralUtilities.check_arguments
1933
1936
  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) -> None:
1937
+ self.__check_target_environmenttype(target_environmenttype)
1934
1938
  repository_folder = GeneralUtilities.resolve_relative_path_from_current_working_directory(repository_folder)
1935
1939
  contains_uncommitted_changes = self.__sc.git_repository_has_uncommitted_changes(repository_folder)
1936
1940
  if is_pre_merge and contains_uncommitted_changes:
@@ -2009,14 +2013,13 @@ class TasksForCommonProjectStructure:
2009
2013
 
2010
2014
  @GeneralUtilities.check_arguments
2011
2015
  def __check_whether_workspace_file_exists(self, repository_folder: str) -> None:
2012
- count=0
2016
+ count = 0
2013
2017
  for file in GeneralUtilities.get_direct_files_of_folder(repository_folder):
2014
2018
  if file.endswith(".code-workspace"):
2015
2019
  count = count + 1
2016
2020
  if count != 1:
2017
2021
  raise ValueError('The repository must contain exactly one ".code-workspace"-file on the top-level.')
2018
2022
 
2019
-
2020
2023
  @GeneralUtilities.check_arguments
2021
2024
  def update_dependency_in_resources_folder(self, update_dependencies_file, dependency_name: str, latest_version_function: str) -> None:
2022
2025
  dependency_folder = GeneralUtilities.resolve_relative_path(f"../Resources/Dependencies/{dependency_name}", update_dependencies_file)
@@ -2129,7 +2132,7 @@ class TasksForCommonProjectStructure:
2129
2132
  for file in GeneralUtilities.get_all_files_of_folder(files_folder):
2130
2133
  if file.endswith(".plantuml"):
2131
2134
  argument = ['-jar', f'{plant_uml_folder}/plantuml.jar', os.path.basename(file).replace("\\", "/"), '-tsvg']
2132
- sc.run_program_argsasarray("java", argument, os.path.dirname(file))
2135
+ sc.run_program_argsasarray("java", argument, os.path.dirname(file),verbosity=0)
2133
2136
 
2134
2137
  @GeneralUtilities.check_arguments
2135
2138
  def load_deb_control_file_content(self, file: str, codeunitname: str, codeunitversion: str, installedsize: int, maintainername: str, maintaineremail: str, description: str,) -> str:
@@ -2161,34 +2164,29 @@ class TasksForCommonProjectStructure:
2161
2164
  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)
2162
2165
  self.__sc.create_deb_package(codeunit_name, binary_folder, control_file_content, deb_output_folder, verbosity, 555)
2163
2166
 
2164
-
2165
2167
  @GeneralUtilities.check_arguments
2166
2168
  def update_year_in_license_file_in_common_scripts_file(self, common_tasks_scripts_file: str) -> None:
2167
- self.update_year_in_license_file(GeneralUtilities.resolve_relative_path("../../..",common_tasks_scripts_file))
2168
-
2169
+ self.update_year_in_license_file(GeneralUtilities.resolve_relative_path("../../..", common_tasks_scripts_file))
2169
2170
 
2170
2171
  @GeneralUtilities.check_arguments
2171
2172
  def update_year_in_license_file(self, repository_folder: str) -> None:
2172
- self.__sc.update_year_in_first_line_of_file(os.path.join(repository_folder,"License.txt"))
2173
-
2173
+ self.__sc.update_year_in_first_line_of_file(os.path.join(repository_folder, "License.txt"))
2174
2174
 
2175
2175
  @GeneralUtilities.check_arguments
2176
2176
  def update_year_for_dotnet_codeunit_in_common_scripts_file(self, common_tasks_scripts_file: str) -> None:
2177
- self.update_year_for_dotnet_codeunit(GeneralUtilities.resolve_relative_path("../..",common_tasks_scripts_file))
2178
-
2177
+ self.update_year_for_dotnet_codeunit(GeneralUtilities.resolve_relative_path("../..", common_tasks_scripts_file))
2179
2178
 
2180
2179
  @GeneralUtilities.check_arguments
2181
2180
  def update_year_for_dotnet_codeunit(self, codeunit_folder: str) -> None:
2182
- codeunit_name=os.path.basename(codeunit_folder)
2183
- csproj_file=os.path.join(codeunit_folder,codeunit_name,f"{codeunit_name}.csproj")
2181
+ codeunit_name = os.path.basename(codeunit_folder)
2182
+ csproj_file = os.path.join(codeunit_folder, codeunit_name, f"{codeunit_name}.csproj")
2184
2183
  self.__sc.update_year_in_copyright_tags(csproj_file)
2185
- csprojtests_file=os.path.join(codeunit_folder,f"{codeunit_name}Tests",f"{codeunit_name}Tests.csproj")
2184
+ csprojtests_file = os.path.join(codeunit_folder, f"{codeunit_name}Tests", f"{codeunit_name}Tests.csproj")
2186
2185
  self.__sc.update_year_in_copyright_tags(csprojtests_file)
2187
- nuspec_file=os.path.join(codeunit_folder,"Other","Build",f"{codeunit_name}.nuspec")
2186
+ nuspec_file = os.path.join(codeunit_folder, "Other", "Build", f"{codeunit_name}.nuspec")
2188
2187
  if os.path.isfile(nuspec_file):
2189
2188
  self.__sc.update_year_in_copyright_tags(nuspec_file)
2190
2189
 
2191
-
2192
2190
  @GeneralUtilities.check_arguments
2193
2191
  def repository_has_codeunits(self, repository: str, ignore_disabled_codeunits: bool = True) -> bool:
2194
2192
  return len(self.get_codeunits(repository, ignore_disabled_codeunits))
@@ -2285,7 +2283,7 @@ class TasksForCommonProjectStructure:
2285
2283
  codeunit_hast_testable_sourcecode = self.codeunit_has_testable_sourcecode(codeunit_file)
2286
2284
  if codeunit_hast_testable_sourcecode:
2287
2285
  GeneralUtilities.write_message_to_stdout('Run "RunTestcases.py"...')
2288
- self.__sc.run_program("python", f"RunTestcases.py{additional_arguments_r}{general_argument}",quality_folder, verbosity=verbosity_for_executed_programs, throw_exception_if_exitcode_is_not_zero=True)
2286
+ self.__sc.run_program("python", f"RunTestcases.py{additional_arguments_r}{general_argument}", quality_folder, verbosity=verbosity_for_executed_programs, throw_exception_if_exitcode_is_not_zero=True)
2289
2287
  self.verify_artifact_exists(codeunit_folder, dict[str, bool]({"TestCoverage": True, "TestCoverageReport": False}))
2290
2288
 
2291
2289
  GeneralUtilities.write_message_to_stdout('Run "Linting.py"...')
@@ -2323,3 +2321,128 @@ class TasksForCommonProjectStructure:
2323
2321
  </cps:artifactsinformation>""")
2324
2322
  # TODO validate artifactsinformation_file against xsd
2325
2323
  GeneralUtilities.write_message_to_stdout(f"Finished building codeunit {codeunit_name} without errors.")
2324
+
2325
+ @GeneralUtilities.check_arguments
2326
+ def generic_update_dependencies(self, repository_folder: str):
2327
+ codeunits = self.get_codeunits(repository_folder)
2328
+ updated_dependencies = False
2329
+ for codeunit in codeunits:
2330
+ codeunit_file = os.path.join(repository_folder, codeunit, f"{codeunit}.codeunit.xml")
2331
+ codeunit_has_updatable_dependencies = self.codeunit_has_updatable_dependencies(codeunit_file)
2332
+ if codeunit_has_updatable_dependencies:
2333
+ codeunit_folder = os.path.join(repository_folder, codeunit)
2334
+ update_dependencies_script_folder = os.path.join(codeunit_folder, "Other")
2335
+ self.__sc.run_program("python", "UpdateDependencies.py", update_dependencies_script_folder)#TODO set verbosity
2336
+ if self.__sc.git_repository_has_uncommitted_changes(repository_folder):
2337
+ version_of_project = self.get_version_of_project(repository_folder)
2338
+ changelog_file = os.path.join(repository_folder, "Other", "Resources", "Changelog", f"v{version_of_project}.md")
2339
+ if not os.path.isfile(changelog_file):
2340
+ GeneralUtilities.write_text_to_file(changelog_file, """# Release notes
2341
+
2342
+ ## Changes
2343
+
2344
+ - Updated dependencies.
2345
+ """)
2346
+ GeneralUtilities.write_message_to_stdout(f"Updated dependencies in codeunit {codeunit}.")
2347
+ updated_dependencies = True
2348
+ else:
2349
+ GeneralUtilities.write_message_to_stdout(f"There are no dependencies to update in codeunit {codeunit}.")
2350
+ if updated_dependencies:
2351
+ self.__sc.run_program("scbuildcodeunits", "--targetenvironment QualityCheck", repository_folder)#TODO set verbosity
2352
+ self.__sc.git_commit(repository_folder, "Updated dependencies")
2353
+
2354
+ class GenericPrepareNewReleaseArguments:
2355
+ current_file: str
2356
+ product_name: str
2357
+ commandline_arguments: list[str]
2358
+
2359
+ def __init__(self, current_file: str, product_name: str, commandline_arguments: list[str]):
2360
+ self.current_file = current_file
2361
+ self.product_name = product_name
2362
+ self.commandline_arguments = commandline_arguments
2363
+
2364
+ @GeneralUtilities.check_arguments
2365
+ def generic_prepare_new_release(self, generic_prepare_new_release_arguments: GenericPrepareNewReleaseArguments):
2366
+
2367
+ # constants
2368
+ folder_of_this_file = os.path.dirname(generic_prepare_new_release_arguments.current_file)
2369
+ build_repository_folder = GeneralUtilities.resolve_relative_path("../..", folder_of_this_file)
2370
+
2371
+ repository_folder = GeneralUtilities.resolve_relative_path(f"../../Submodules/{generic_prepare_new_release_arguments.product_name}", folder_of_this_file)
2372
+ verbosity: int = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(generic_prepare_new_release_arguments.commandline_arguments, 1)
2373
+ merge_source_branch = "other/next-release"
2374
+
2375
+ # prepare
2376
+ self.assert_no_uncommitted_changes(repository_folder)
2377
+ self.__sc.git_checkout(repository_folder, merge_source_branch)
2378
+ self.generic_update_dependencies(repository_folder)
2379
+ self.merge_to_main_branch(repository_folder, merge_source_branch, verbosity=verbosity, fast_forward_source_branch=True)
2380
+ self.__sc.git_commit(build_repository_folder, "Updated submodule due to merge to main-branch.")
2381
+
2382
+ class GenericCreateReleaseArguments():
2383
+ current_file: str
2384
+ product_name: str
2385
+ common_remote_name: str
2386
+ artifacts_target_folder: str
2387
+ commandline_arguments: list[str]
2388
+
2389
+ def __init__(self, current_file: str, product_name: str, common_remote_name: str, artifacts_target_folder: str,commandline_arguments: list[str]):
2390
+ self.current_file = current_file
2391
+ self.product_name = product_name
2392
+ self.common_remote_name = common_remote_name
2393
+ self.artifacts_target_folder = artifacts_target_folder
2394
+ self.commandline_arguments = commandline_arguments
2395
+
2396
+ @GeneralUtilities.check_arguments
2397
+ def generic_create_release(self, generic_create_release_arguments:GenericCreateReleaseArguments) -> str:
2398
+ folder_of_this_file = os.path.dirname(generic_create_release_arguments.current_file)
2399
+ build_repository_folder = GeneralUtilities.resolve_relative_path("../..", folder_of_this_file)
2400
+ repository_folder_name = generic_create_release_arguments.product_name
2401
+ repository_folder = GeneralUtilities.resolve_relative_path(f"../../Submodules/{generic_create_release_arguments.product_name}", folder_of_this_file)
2402
+ additional_arguments_file = os.path.join(folder_of_this_file, "AdditionalArguments.configuration")
2403
+ verbosity: int = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(generic_create_release_arguments.commandline_arguments, 1)
2404
+ createReleaseConfiguration: CreateReleaseConfiguration = CreateReleaseConfiguration(
2405
+ 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)
2406
+ self.__sc.git_commit(build_repository_folder, "Updated submodule")
2407
+
2408
+ # create release
2409
+ new_version = self.merge_to_stable_branch(generic_create_release_arguments.current_file, createReleaseConfiguration)
2410
+ return new_version
2411
+
2412
+ class UpdateHTTPDocumentationArguments:
2413
+ current_file: str
2414
+ product_name: str
2415
+ common_remote_name: str
2416
+ new_project_version: str
2417
+ reference_repository_name: str
2418
+ commandline_arguments: list[str]
2419
+ main_branch_name: str
2420
+
2421
+ def __init__(self, current_file: str, product_name: str, common_remote_name: str, new_project_version: str, reference_repository_name: str, commandline_arguments: list[str]):
2422
+ self.current_file = current_file
2423
+ self.product_name = product_name
2424
+ self.common_remote_name = common_remote_name
2425
+ self.new_project_version = new_project_version
2426
+ self.reference_repository_name = reference_repository_name
2427
+ self.commandline_arguments = commandline_arguments
2428
+ self.main_branch_name = "main"
2429
+
2430
+ @GeneralUtilities.check_arguments
2431
+ def update_http_documentation(self, update_http_documentation_arguments: UpdateHTTPDocumentationArguments):
2432
+ folder_of_this_file = str(os.path.dirname(update_http_documentation_arguments.current_file))
2433
+
2434
+ ref_repo = GeneralUtilities.resolve_relative_path(f"../../Submodules/{update_http_documentation_arguments.reference_repository_name}", folder_of_this_file)
2435
+ self.__sc.git_checkout(ref_repo, update_http_documentation_arguments.main_branch_name)
2436
+
2437
+ # update reference
2438
+ target = os.path.join(ref_repo, "Reference", update_http_documentation_arguments.product_name)
2439
+ GeneralUtilities.ensure_directory_does_not_exist(target)
2440
+ shutil.copytree(GeneralUtilities.resolve_relative_path(f"../../Submodules/{update_http_documentation_arguments.product_name}Reference/ReferenceContent", folder_of_this_file), target)
2441
+ self.__sc.git_commit(ref_repo, f"Added reference of {update_http_documentation_arguments.product_name} v{update_http_documentation_arguments.new_project_version}")
2442
+
2443
+ # Sync reference-repository
2444
+ self.__sc.git_fetch(ref_repo, update_http_documentation_arguments.common_remote_name)
2445
+ self.__sc.git_merge(ref_repo, update_http_documentation_arguments.common_remote_name+"/"+update_http_documentation_arguments.main_branch_name, update_http_documentation_arguments.main_branch_name)
2446
+ self.__sc.git_checkout(ref_repo, update_http_documentation_arguments.main_branch_name)
2447
+ self.__sc.git_push(ref_repo, update_http_documentation_arguments.common_remote_name, update_http_documentation_arguments.main_branch_name, update_http_documentation_arguments.main_branch_name)
2448
+ self.__sc.git_commit(GeneralUtilities.resolve_relative_path("../..", folder_of_this_file), f"Updated content of {update_http_documentation_arguments.product_name} v{update_http_documentation_arguments.new_project_version} in {update_http_documentation_arguments.reference_repository_name}-submodule")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ScriptCollection
3
- Version: 3.4.58
3
+ Version: 3.5.0
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
@@ -22,25 +22,25 @@ Classifier: Topic :: Terminals
22
22
  Classifier: Topic :: Utilities
23
23
  Requires-Python: >=3.10
24
24
  Description-Content-Type: text/markdown
25
- Requires-Dist: build >=1.1.1
26
- Requires-Dist: coverage >=7.4.4
27
- Requires-Dist: cyclonedx-bom >=4.1.3
25
+ Requires-Dist: build >=1.2.1
26
+ Requires-Dist: coverage >=7.5.0
27
+ Requires-Dist: cyclonedx-bom >=4.4.3
28
28
  Requires-Dist: defusedxml >=0.7.1
29
29
  Requires-Dist: keyboard >=0.13.5
30
30
  Requires-Dist: lcov-cobertura >=2.0.2
31
- Requires-Dist: lxml >=5.1.0
31
+ Requires-Dist: lxml >=5.2.1
32
32
  Requires-Dist: ntplib >=0.4.0
33
- Requires-Dist: Pillow >=10.2.0
33
+ Requires-Dist: Pillow >=10.3.0
34
34
  Requires-Dist: pycdlib >=1.14.0
35
35
  Requires-Dist: Pygments >=2.17.2
36
36
  Requires-Dist: pylint >=3.1.0
37
37
  Requires-Dist: pyOpenSSL >=24.1.0
38
38
  Requires-Dist: PyPDF2 >=3.0.1
39
- Requires-Dist: pytest >=8.1.1
39
+ Requires-Dist: pytest >=8.2.0
40
40
  Requires-Dist: qrcode >=7.4.2
41
- Requires-Dist: send2trash >=1.8.2
41
+ Requires-Dist: send2trash >=1.8.3
42
42
  Requires-Dist: twine >=5.0.0
43
- Requires-Dist: xmlschema >=3.1.0
43
+ Requires-Dist: xmlschema >=3.3.1
44
44
 
45
45
  # ScriptCollection
46
46
 
@@ -0,0 +1,14 @@
1
+ ScriptCollection/Executables.py,sha256=F8ar_pRplVZm0mHLJ_Ono5HKTfqr6wTceG3Hcbx_tow,19282
2
+ ScriptCollection/GeneralUtilities.py,sha256=Mcp6ghb6AbS1KsOjEnRw3x4a4mBrAZ6DAjV2j8-LZFM,35589
3
+ ScriptCollection/ProgramRunnerBase.py,sha256=2kyOuoM3oFjBfLc9Q5t5RTz7Ya2CjUxFtB1rBBDmnjU,1937
4
+ ScriptCollection/ProgramRunnerEpew.py,sha256=nIzY4dG6W-xEpkeoTbozwNZtFSIo-bU_W6t6u1AZKtE,6275
5
+ ScriptCollection/ProgramRunnerPopen.py,sha256=kV7KVuDenKjOyNBFurMTcuhuLuLZ74MaaSrwaPjaHCs,3158
6
+ ScriptCollection/ScriptCollectionCore.py,sha256=LXHRp3sWZmIdWRhOXFbQxGE4aPel194AhMXgD8LCKOs,92657
7
+ ScriptCollection/TasksForCommonProjectStructure.py,sha256=4ZxLkYtT7nszV46AT0E7_TuAziFokFnG1UcZ9VFYfzk,173711
8
+ ScriptCollection/UpdateCertificates.py,sha256=3C_E9og5SZec35aD3BFYLchzJtonsg1KR4enFCb5Jzk,7914
9
+ ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ ScriptCollection-3.5.0.dist-info/METADATA,sha256=RVO_ZaAz9cLgXhOTyAZUMvA7eqk9pMGPvmAUEcDEqeQ,7648
11
+ ScriptCollection-3.5.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
12
+ ScriptCollection-3.5.0.dist-info/entry_points.txt,sha256=dwvB9HRGvqst5xlYIGmmwuFN7lBKhxvndmnNrQOfu8w,2153
13
+ ScriptCollection-3.5.0.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
14
+ ScriptCollection-3.5.0.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- ScriptCollection/Executables.py,sha256=F8ar_pRplVZm0mHLJ_Ono5HKTfqr6wTceG3Hcbx_tow,19282
2
- ScriptCollection/GeneralUtilities.py,sha256=Mcp6ghb6AbS1KsOjEnRw3x4a4mBrAZ6DAjV2j8-LZFM,35589
3
- ScriptCollection/ProgramRunnerBase.py,sha256=2kyOuoM3oFjBfLc9Q5t5RTz7Ya2CjUxFtB1rBBDmnjU,1937
4
- ScriptCollection/ProgramRunnerEpew.py,sha256=nIzY4dG6W-xEpkeoTbozwNZtFSIo-bU_W6t6u1AZKtE,6275
5
- ScriptCollection/ProgramRunnerPopen.py,sha256=veDNRg2Z0u0vd4iKWAycVFKbTm_uWYfuK6NTiwlbgrM,3230
6
- ScriptCollection/ScriptCollectionCore.py,sha256=BhKnb3B9-EJDdpBCZ-OxfJ3gCYw3l2gTlTS6f6p4U94,95610
7
- ScriptCollection/TasksForCommonProjectStructure.py,sha256=2JjsnakLb9cL8x0KaSKoEtJhQXGGcgy9cBYGhbW7IYY,164656
8
- ScriptCollection/UpdateCertificates.py,sha256=3C_E9og5SZec35aD3BFYLchzJtonsg1KR4enFCb5Jzk,7914
9
- ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- ScriptCollection-3.4.58.dist-info/METADATA,sha256=ooyyqkaSxGR4PUclox2lThp46-edMlCMI8aBO7TQDRU,7649
11
- ScriptCollection-3.4.58.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
12
- ScriptCollection-3.4.58.dist-info/entry_points.txt,sha256=dwvB9HRGvqst5xlYIGmmwuFN7lBKhxvndmnNrQOfu8w,2153
13
- ScriptCollection-3.4.58.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
14
- ScriptCollection-3.4.58.dist-info/RECORD,,