ScriptCollection 3.5.1__py3-none-any.whl → 3.5.2__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.
@@ -4,7 +4,7 @@ import json
4
4
  import binascii
5
5
  import filecmp
6
6
  import hashlib
7
- from io import BytesIO
7
+ from io import BufferedReader, BytesIO
8
8
  import itertools
9
9
  import math
10
10
  import os
@@ -29,7 +29,7 @@ from .ProgramRunnerPopen import ProgramRunnerPopen
29
29
  from .ProgramRunnerEpew import ProgramRunnerEpew, CustomEpewArgument
30
30
 
31
31
 
32
- version = "3.5.1"
32
+ version = "3.5.2"
33
33
  __version__ = version
34
34
 
35
35
 
@@ -59,7 +59,8 @@ class ScriptCollectionCore:
59
59
  errorsonly_argument = ""
60
60
  else:
61
61
  errorsonly_argument = " --errors-only"
62
- (exit_code, stdout, stderr, _) = self.run_program("pylint", filename+errorsonly_argument, working_directory, throw_exception_if_exitcode_is_not_zero=False)
62
+ (exit_code, stdout, stderr, _) = self.run_program("pylint", filename +
63
+ errorsonly_argument, working_directory, throw_exception_if_exitcode_is_not_zero=False)
63
64
  if (exit_code != 0):
64
65
  errors.append(f"Linting-issues of {file}:")
65
66
  errors.append(f"Pylint-exitcode: {exit_code}")
@@ -73,15 +74,18 @@ class ScriptCollectionCore:
73
74
 
74
75
  @GeneralUtilities.check_arguments
75
76
  def replace_version_in_dockerfile_file(self, dockerfile: str, new_version_value: str) -> None:
76
- GeneralUtilities.write_text_to_file(dockerfile, re.sub("ARG Version=\"\\d+\\.\\d+\\.\\d+\"", f"ARG Version=\"{new_version_value}\"", GeneralUtilities.read_text_from_file(dockerfile)))
77
+ GeneralUtilities.write_text_to_file(dockerfile, re.sub(
78
+ "ARG Version=\"\\d+\\.\\d+\\.\\d+\"", f"ARG Version=\"{new_version_value}\"", GeneralUtilities.read_text_from_file(dockerfile)))
77
79
 
78
80
  @GeneralUtilities.check_arguments
79
81
  def replace_version_in_python_file(self, file: str, new_version_value: str):
80
- GeneralUtilities.write_text_to_file(file, re.sub("version = \"\\d+\\.\\d+\\.\\d+\"", f"version = \"{new_version_value}\"", GeneralUtilities.read_text_from_file(file)))
82
+ GeneralUtilities.write_text_to_file(file, re.sub(
83
+ "version = \"\\d+\\.\\d+\\.\\d+\"", f"version = \"{new_version_value}\"", GeneralUtilities.read_text_from_file(file)))
81
84
 
82
85
  @GeneralUtilities.check_arguments
83
86
  def replace_version_in_ini_file(self, file: str, new_version_value: str):
84
- GeneralUtilities.write_text_to_file(file, re.sub("version = \\d+\\.\\d+\\.\\d+", f"version = {new_version_value}", GeneralUtilities.read_text_from_file(file)))
87
+ GeneralUtilities.write_text_to_file(file, re.sub(
88
+ "version = \\d+\\.\\d+\\.\\d+", f"version = {new_version_value}", GeneralUtilities.read_text_from_file(file)))
85
89
 
86
90
  @GeneralUtilities.check_arguments
87
91
  def replace_version_in_nuspec_file(self, nuspec_file: str, new_version: str) -> None:
@@ -90,9 +94,11 @@ class ScriptCollectionCore:
90
94
  versiononlyregex = f"^{versionregex}$"
91
95
  pattern = re.compile(versiononlyregex)
92
96
  if pattern.match(new_version):
93
- GeneralUtilities.write_text_to_file(nuspec_file, re.sub(f"<version>{versionregex}<\\/version>", f"<version>{new_version}</version>", GeneralUtilities.read_text_from_file(nuspec_file)))
97
+ GeneralUtilities.write_text_to_file(nuspec_file, re.sub(
98
+ f"<version>{versionregex}<\\/version>", f"<version>{new_version}</version>", GeneralUtilities.read_text_from_file(nuspec_file)))
94
99
  else:
95
- raise ValueError(f"Version '{new_version}' does not match version-regex '{versiononlyregex}'")
100
+ raise ValueError(
101
+ f"Version '{new_version}' does not match version-regex '{versiononlyregex}'")
96
102
 
97
103
  @GeneralUtilities.check_arguments
98
104
  def replace_version_in_csproj_file(self, csproj_file: str, current_version: str):
@@ -101,35 +107,44 @@ class ScriptCollectionCore:
101
107
  pattern = re.compile(versiononlyregex)
102
108
  if pattern.match(current_version):
103
109
  for tag in ["Version", "AssemblyVersion", "FileVersion"]:
104
- GeneralUtilities.write_text_to_file(csproj_file, re.sub(f"<{tag}>{versionregex}(.\\d+)?<\\/{tag}>", f"<{tag}>{current_version}</{tag}>", GeneralUtilities.read_text_from_file(csproj_file)))
110
+ GeneralUtilities.write_text_to_file(csproj_file, re.sub(
111
+ f"<{tag}>{versionregex}(.\\d+)?<\\/{tag}>", f"<{tag}>{current_version}</{tag}>", GeneralUtilities.read_text_from_file(csproj_file)))
105
112
  else:
106
- raise ValueError(f"Version '{current_version}' does not match version-regex '{versiononlyregex}'")
113
+ raise ValueError(
114
+ f"Version '{current_version}' does not match version-regex '{versiononlyregex}'")
107
115
 
108
116
  @GeneralUtilities.check_arguments
109
117
  def push_nuget_build_artifact(self, nupkg_file: str, registry_address: str, api_key: str, verbosity: int = 1):
110
118
  nupkg_file_name = os.path.basename(nupkg_file)
111
119
  nupkg_file_folder = os.path.dirname(nupkg_file)
112
- self.run_program("dotnet", f"nuget push {nupkg_file_name} --force-english-output --source {registry_address} --api-key {api_key}", nupkg_file_folder, verbosity)
120
+ self.run_program(
121
+ "dotnet", f"nuget push {nupkg_file_name} --force-english-output --source {registry_address} --api-key {api_key}", nupkg_file_folder, verbosity)
113
122
 
114
123
  @GeneralUtilities.check_arguments
115
124
  def dotnet_build(self, repository_folder: str, projectname: str, configuration: str):
116
- self.run_program("dotnet", f"clean -c {configuration}", repository_folder)
117
- self.run_program("dotnet", f"build {projectname}/{projectname}.csproj -c {configuration}", repository_folder)
125
+ self.run_program(
126
+ "dotnet", f"clean -c {configuration}", repository_folder)
127
+ self.run_program(
128
+ "dotnet", f"build {projectname}/{projectname}.csproj -c {configuration}", repository_folder)
118
129
 
119
130
  @GeneralUtilities.check_arguments
120
131
  def find_file_by_extension(self, folder: str, extension: str):
121
- result = [file for file in GeneralUtilities.get_direct_files_of_folder(folder) if file.endswith(f".{extension}")]
132
+ result = [file for file in GeneralUtilities.get_direct_files_of_folder(
133
+ folder) if file.endswith(f".{extension}")]
122
134
  result_length = len(result)
123
135
  if result_length == 0:
124
- raise FileNotFoundError(f"No file available in folder '{folder}' with extension '{extension}'.")
136
+ raise FileNotFoundError(
137
+ f"No file available in folder '{folder}' with extension '{extension}'.")
125
138
  if result_length == 1:
126
139
  return result[0]
127
140
  else:
128
- raise ValueError(f"Multiple values available in folder '{folder}' with extension '{extension}'.")
141
+ raise ValueError(
142
+ f"Multiple values available in folder '{folder}' with extension '{extension}'.")
129
143
 
130
144
  @GeneralUtilities.check_arguments
131
145
  def commit_is_signed_by_key(self, repository_folder: str, revision_identifier: str, key: str) -> bool:
132
- result = self.run_program("git", f"verify-commit {revision_identifier}", repository_folder, throw_exception_if_exitcode_is_not_zero=False)
146
+ result = self.run_program(
147
+ "git", f"verify-commit {revision_identifier}", repository_folder, throw_exception_if_exitcode_is_not_zero=False)
133
148
  if (result[0] != 0):
134
149
  return False
135
150
  if (not GeneralUtilities.contains_line(result[1].splitlines(), f"gpg\\:\\ using\\ [A-Za-z0-9]+\\ key\\ [A-Za-z0-9]+{key}")):
@@ -151,8 +166,10 @@ class ScriptCollectionCore:
151
166
  subfolder_argument = ""
152
167
  else:
153
168
  subfolder_argument = f" -- {subfolder}"
154
- log_result = self.run_program("git", f'log --pretty=%aN{space_character}%aE%n%cN{space_character}%cE HEAD{subfolder_argument}', repository_folder, verbosity=0)
155
- plain_content: list[str] = list(set([line for line in log_result[1].split("\n") if len(line) > 0]))
169
+ log_result = self.run_program(
170
+ "git", f'log --pretty=%aN{space_character}%aE%n%cN{space_character}%cE HEAD{subfolder_argument}', repository_folder, verbosity=0)
171
+ plain_content: list[str] = list(
172
+ set([line for line in log_result[1].split("\n") if len(line) > 0]))
156
173
  result: list[tuple[str, str]] = []
157
174
  for item in plain_content:
158
175
  if len(re.findall(space_character, item)) == 1:
@@ -166,9 +183,11 @@ class ScriptCollectionCore:
166
183
  def get_commit_ids_between_dates(self, repository_folder: str, since: datetime, until: datetime, ignore_commits_which_are_not_in_history_of_head: bool = True) -> None:
167
184
  since_as_string = self.__datetime_to_string_for_git(since)
168
185
  until_as_string = self.__datetime_to_string_for_git(until)
169
- result = filter(lambda line: not GeneralUtilities.string_is_none_or_whitespace(line), self.run_program("git", f'log --since "{since_as_string}" --until "{until_as_string}" --pretty=format:"%H" --no-patch', repository_folder, throw_exception_if_exitcode_is_not_zero=True)[1].split("\n").replace("\r", ""))
186
+ result = filter(lambda line: not GeneralUtilities.string_is_none_or_whitespace(line), self.run_program(
187
+ "git", f'log --since "{since_as_string}" --until "{until_as_string}" --pretty=format:"%H" --no-patch', repository_folder, throw_exception_if_exitcode_is_not_zero=True)[1].split("\n").replace("\r", ""))
170
188
  if ignore_commits_which_are_not_in_history_of_head:
171
- result = [commit_id for commit_id in result if self.git_commit_is_ancestor(repository_folder, commit_id)]
189
+ result = [commit_id for commit_id in result if self.git_commit_is_ancestor(
190
+ repository_folder, commit_id)]
172
191
  return result
173
192
 
174
193
  @GeneralUtilities.check_arguments
@@ -177,17 +196,20 @@ class ScriptCollectionCore:
177
196
 
178
197
  @GeneralUtilities.check_arguments
179
198
  def git_commit_is_ancestor(self, repository_folder: str, ancestor: str, descendant: str = "HEAD") -> bool:
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]
199
+ exit_code = self.run_program_argsasarray(
200
+ "git", ["merge-base", "--is-ancestor", ancestor, descendant], repository_folder, throw_exception_if_exitcode_is_not_zero=False)[0]
181
201
  if exit_code == 0:
182
202
  return True
183
203
  elif exit_code == 1:
184
204
  return False
185
205
  else:
186
- raise ValueError(f"Can not calculate if {ancestor} is an ancestor of {descendant} in repository {repository_folder}.")
206
+ raise ValueError(
207
+ f"Can not calculate if {ancestor} is an ancestor of {descendant} in repository {repository_folder}.")
187
208
 
188
209
  @GeneralUtilities.check_arguments
189
210
  def __git_changes_helper(self, repository_folder: str, arguments_as_array: list[str]) -> bool:
190
- lines = GeneralUtilities.string_to_lines(self.run_program_argsasarray("git", arguments_as_array, repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)[1], False)
211
+ lines = GeneralUtilities.string_to_lines(self.run_program_argsasarray(
212
+ "git", arguments_as_array, repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)[1], False)
191
213
  for line in lines:
192
214
  if GeneralUtilities.string_has_content(line):
193
215
  return True
@@ -223,36 +245,43 @@ class ScriptCollectionCore:
223
245
 
224
246
  @GeneralUtilities.check_arguments
225
247
  def git_get_commit_id(self, repository_folder: str, commit: str = "HEAD") -> str:
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)
248
+ result: tuple[int, str, str, int] = self.run_program_argsasarray(
249
+ "git", ["rev-parse", "--verify", commit], repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
227
250
  return result[1].replace('\n', '')
228
251
 
229
252
  @GeneralUtilities.check_arguments
230
253
  def git_get_commit_date(self, repository_folder: str, commit: str = "HEAD") -> datetime:
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)
254
+ result: tuple[int, str, str, int] = self.run_program_argsasarray(
255
+ "git", ["show", "-s", "--format=%ci", commit], repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
232
256
  date_as_string = result[1].replace('\n', '')
233
257
  result = datetime.strptime(date_as_string, '%Y-%m-%d %H:%M:%S %z')
234
258
  return result
235
259
 
236
260
  @GeneralUtilities.check_arguments
237
261
  def git_fetch(self, folder: str, remotename: str = "--all") -> None:
238
- self.run_program_argsasarray("git", ["fetch", remotename, "--tags", "--prune"], folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
262
+ self.run_program_argsasarray("git", ["fetch", remotename, "--tags", "--prune"],
263
+ folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
239
264
 
240
265
  @GeneralUtilities.check_arguments
241
266
  def git_fetch_in_bare_repository(self, folder: str, remotename, localbranch: str, remotebranch: str) -> None:
242
- self.run_program_argsasarray("git", ["fetch", remotename, f"{remotebranch}:{localbranch}"], folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
267
+ self.run_program_argsasarray("git", [
268
+ "fetch", remotename, f"{remotebranch}:{localbranch}"], folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
243
269
 
244
270
  @GeneralUtilities.check_arguments
245
271
  def git_remove_branch(self, folder: str, branchname: str) -> None:
246
- self.run_program("git", f"branch -D {branchname}", folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
272
+ self.run_program("git", f"branch -D {branchname}", folder,
273
+ throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
247
274
 
248
275
  @GeneralUtilities.check_arguments
249
276
  def git_push(self, folder: str, remotename: str, localbranchname: str, remotebranchname: str, forcepush: bool = False, pushalltags: bool = True, verbosity: int = 0) -> None:
250
- argument = ["push", "--recurse-submodules=on-demand", remotename, f"{localbranchname}:{remotebranchname}"]
277
+ argument = ["push", "--recurse-submodules=on-demand",
278
+ remotename, f"{localbranchname}:{remotebranchname}"]
251
279
  if (forcepush):
252
280
  argument.append("--force")
253
281
  if (pushalltags):
254
282
  argument.append("--tags")
255
- result: tuple[int, str, str, int] = self.run_program_argsasarray("git", argument, folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=verbosity, print_errors_as_information=True)
283
+ result: tuple[int, str, str, int] = self.run_program_argsasarray("git", argument, folder, throw_exception_if_exitcode_is_not_zero=True,
284
+ verbosity=verbosity, print_errors_as_information=True)
256
285
  return result[1].replace('\r', '').replace('\n', '')
257
286
 
258
287
  @GeneralUtilities.check_arguments
@@ -266,11 +295,13 @@ class ScriptCollectionCore:
266
295
  args.append("--remote-submodules")
267
296
  if mirror:
268
297
  args.append("--mirror")
269
- self.run_program_argsasarray("git", args, os.getcwd(), throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
298
+ self.run_program_argsasarray("git", args, os.getcwd(
299
+ ), throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
270
300
 
271
301
  @GeneralUtilities.check_arguments
272
302
  def git_get_all_remote_names(self, directory: str) -> list[str]:
273
- result = GeneralUtilities.string_to_lines(self.run_program_argsasarray("git", ["remote"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)[1], False)
303
+ result = GeneralUtilities.string_to_lines(self.run_program_argsasarray(
304
+ "git", ["remote"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)[1], False)
274
305
  return result
275
306
 
276
307
  @GeneralUtilities.check_arguments
@@ -286,36 +317,45 @@ class ScriptCollectionCore:
286
317
  @GeneralUtilities.check_arguments
287
318
  def git_add_or_set_remote_address(self, directory: str, remote_name: str, remote_address: str) -> None:
288
319
  if (self.repository_has_remote_with_specific_name(directory, remote_name)):
289
- self.run_program_argsasarray("git", ['remote', 'set-url', 'remote_name', remote_address], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
320
+ self.run_program_argsasarray("git", ['remote', 'set-url', 'remote_name', remote_address],
321
+ directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
290
322
  else:
291
- self.run_program_argsasarray("git", ['remote', 'add', remote_name, remote_address], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
323
+ self.run_program_argsasarray("git", ['remote', 'add', remote_name, remote_address],
324
+ directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
292
325
 
293
326
  @GeneralUtilities.check_arguments
294
327
  def git_stage_all_changes(self, directory: str) -> None:
295
- self.run_program_argsasarray("git", ["add", "-A"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
328
+ self.run_program_argsasarray("git", [
329
+ "add", "-A"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
296
330
 
297
331
  @GeneralUtilities.check_arguments
298
332
  def git_unstage_all_changes(self, directory: str) -> None:
299
- self.run_program_argsasarray("git", ["reset"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
333
+ self.run_program_argsasarray("git", [
334
+ "reset"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
300
335
 
301
336
  @GeneralUtilities.check_arguments
302
337
  def git_stage_file(self, directory: str, file: str) -> None:
303
- self.run_program_argsasarray("git", ['stage', file], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
338
+ self.run_program_argsasarray("git", [
339
+ 'stage', file], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
304
340
 
305
341
  @GeneralUtilities.check_arguments
306
342
  def git_unstage_file(self, directory: str, file: str) -> None:
307
- self.run_program_argsasarray("git", ['reset', file], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
343
+ self.run_program_argsasarray("git", [
344
+ 'reset', file], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
308
345
 
309
346
  @GeneralUtilities.check_arguments
310
347
  def git_discard_unstaged_changes_of_file(self, directory: str, file: str) -> None:
311
348
  """Caution: This method works really only for 'changed' files yet. So this method does not work properly for new or renamed files."""
312
- self.run_program_argsasarray("git", ['checkout', file], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
349
+ self.run_program_argsasarray("git", [
350
+ 'checkout', file], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
313
351
 
314
352
  @GeneralUtilities.check_arguments
315
353
  def git_discard_all_unstaged_changes(self, directory: str) -> None:
316
354
  """Caution: This function executes 'git clean -df'. This can delete files which maybe should not be deleted. Be aware of that."""
317
- self.run_program_argsasarray("git", ['clean', '-df'], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
318
- self.run_program_argsasarray("git", ['checkout', '.'], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
355
+ self.run_program_argsasarray("git", [
356
+ 'clean', '-df'], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
357
+ self.run_program_argsasarray("git", [
358
+ 'checkout', '.'], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
319
359
 
320
360
  @GeneralUtilities.check_arguments
321
361
  def git_commit(self, directory: str, message: str, author_name: str = None, author_email: str = None, stage_all_changes: bool = True,
@@ -328,7 +368,8 @@ class ScriptCollectionCore:
328
368
  argument = ['commit', '--quiet', '--allow-empty', '--message', message]
329
369
  if (GeneralUtilities.string_has_content(author_name)):
330
370
  argument.append(f'--author="{author_name} <{author_email}>"')
331
- git_repository_has_uncommitted_changes = self.git_repository_has_uncommitted_changes(directory)
371
+ git_repository_has_uncommitted_changes = self.git_repository_has_uncommitted_changes(
372
+ directory)
332
373
 
333
374
  if git_repository_has_uncommitted_changes:
334
375
  do_commit = True
@@ -336,17 +377,22 @@ class ScriptCollectionCore:
336
377
  self.git_stage_all_changes(directory)
337
378
  else:
338
379
  if no_changes_behavior == 0:
339
- GeneralUtilities.write_message_to_stdout(f"Commit '{message}' will not be done because there are no changes to commit in repository '{directory}'")
380
+ GeneralUtilities.write_message_to_stdout(
381
+ f"Commit '{message}' will not be done because there are no changes to commit in repository '{directory}'")
340
382
  do_commit = False
341
383
  if no_changes_behavior == 1:
342
- GeneralUtilities.write_message_to_stdout(f"There are no changes to commit in repository '{directory}'. Commit '{message}' will be done anyway.")
384
+ GeneralUtilities.write_message_to_stdout(
385
+ f"There are no changes to commit in repository '{directory}'. Commit '{message}' will be done anyway.")
343
386
  do_commit = True
344
387
  if no_changes_behavior == 2:
345
- raise RuntimeError(f"There are no changes to commit in repository '{directory}'. Commit '{message}' will not be done.")
388
+ raise RuntimeError(
389
+ f"There are no changes to commit in repository '{directory}'. Commit '{message}' will not be done.")
346
390
 
347
391
  if do_commit:
348
- GeneralUtilities.write_message_to_stdout(f"Commit changes in '{directory}'")
349
- self.run_program_argsasarray("git", argument, directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
392
+ GeneralUtilities.write_message_to_stdout(
393
+ f"Commit changes in '{directory}'")
394
+ self.run_program_argsasarray(
395
+ "git", argument, directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
350
396
 
351
397
  return self.git_get_commit_id(directory)
352
398
 
@@ -357,20 +403,25 @@ class ScriptCollectionCore:
357
403
  if message is None:
358
404
  message = f"Created {target_for_tag}"
359
405
  argument.extend(["-s", '-m', message])
360
- self.run_program_argsasarray("git", argument, directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
406
+ self.run_program_argsasarray(
407
+ "git", argument, directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
361
408
 
362
409
  @GeneralUtilities.check_arguments
363
410
  def git_delete_tag(self, directory: str, tag: str) -> None:
364
- self.run_program_argsasarray("git", ["tag", "--delete", tag], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
411
+ self.run_program_argsasarray("git", [
412
+ "tag", "--delete", tag], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
365
413
 
366
414
  @GeneralUtilities.check_arguments
367
415
  def git_checkout(self, directory: str, branch: str) -> None:
368
- self.run_program_argsasarray("git", ["checkout", branch], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
369
- self.run_program_argsasarray("git", ["submodule", "update", "--recursive"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
416
+ self.run_program_argsasarray("git", [
417
+ "checkout", branch], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
418
+ self.run_program_argsasarray("git", ["submodule", "update", "--recursive"],
419
+ directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
370
420
 
371
421
  @GeneralUtilities.check_arguments
372
422
  def git_merge_abort(self, directory: str) -> None:
373
- self.run_program_argsasarray("git", ["merge", "--abort"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
423
+ self.run_program_argsasarray("git", [
424
+ "merge", "--abort"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
374
425
 
375
426
  @GeneralUtilities.check_arguments
376
427
  def git_merge(self, directory: str, sourcebranch: str, targetbranch: str, fastforward: bool = True, commit: bool = True, commit_message: str = None) -> str:
@@ -384,7 +435,8 @@ class ScriptCollectionCore:
384
435
  args.append("-m")
385
436
  args.append(commit_message)
386
437
  args.append(sourcebranch)
387
- self.run_program_argsasarray("git", args, directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
438
+ self.run_program_argsasarray(
439
+ "git", args, directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
388
440
  return self.git_get_commit_id(directory)
389
441
 
390
442
  @GeneralUtilities.check_arguments
@@ -405,7 +457,8 @@ class ScriptCollectionCore:
405
457
  self.git_fetch(target_directory)
406
458
  else:
407
459
  # clone
408
- self.git_clone(target_repository, source_repository, include_submodules=True, mirror=True)
460
+ self.git_clone(target_repository, source_repository,
461
+ include_submodules=True, mirror=True)
409
462
 
410
463
  def get_git_submodules(self, folder: str) -> list[str]:
411
464
  e = self.run_program("git", "submodule status", folder)
@@ -422,32 +475,39 @@ class ScriptCollectionCore:
422
475
 
423
476
  @GeneralUtilities.check_arguments
424
477
  def file_is_git_ignored(self, file_in_repository: str, repositorybasefolder: str) -> None:
425
- exit_code = self.run_program_argsasarray("git", ['check-ignore', file_in_repository], repositorybasefolder, throw_exception_if_exitcode_is_not_zero=False, verbosity=0)[0]
478
+ exit_code = self.run_program_argsasarray(
479
+ "git", ['check-ignore', file_in_repository], repositorybasefolder, throw_exception_if_exitcode_is_not_zero=False, verbosity=0)[0]
426
480
  if (exit_code == 0):
427
481
  return True
428
482
  if (exit_code == 1):
429
483
  return False
430
- raise ValueError(f"Unable to calculate whether '{file_in_repository}' in repository '{repositorybasefolder}' is ignored due to git-exitcode {exit_code}.")
484
+ raise ValueError(
485
+ f"Unable to calculate whether '{file_in_repository}' in repository '{repositorybasefolder}' is ignored due to git-exitcode {exit_code}.")
431
486
 
432
487
  @GeneralUtilities.check_arguments
433
488
  def git_discard_all_changes(self, repository: str) -> None:
434
- self.run_program_argsasarray("git", ["reset", "HEAD", "."], repository, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
435
- self.run_program_argsasarray("git", ["checkout", "."], repository, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
489
+ self.run_program_argsasarray("git", [
490
+ "reset", "HEAD", "."], repository, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
491
+ self.run_program_argsasarray("git", [
492
+ "checkout", "."], repository, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
436
493
 
437
494
  @GeneralUtilities.check_arguments
438
495
  def git_get_current_branch_name(self, repository: str) -> str:
439
- result = self.run_program_argsasarray("git", ["rev-parse", "--abbrev-ref", "HEAD"], repository, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
496
+ result = self.run_program_argsasarray(
497
+ "git", ["rev-parse", "--abbrev-ref", "HEAD"], repository, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
440
498
  return result[1].replace("\r", "").replace("\n", "")
441
499
 
442
500
  @GeneralUtilities.check_arguments
443
501
  def git_get_commitid_of_tag(self, repository: str, tag: str) -> str:
444
- stdout = self.run_program_argsasarray("git", ["rev-list", "-n", "1", tag], repository, verbosity=0)
502
+ stdout = self.run_program_argsasarray(
503
+ "git", ["rev-list", "-n", "1", tag], repository, verbosity=0)
445
504
  result = stdout[1].replace("\r", "").replace("\n", "")
446
505
  return result
447
506
 
448
507
  @GeneralUtilities.check_arguments
449
508
  def git_get_tags(self, repository: str) -> list[str]:
450
- tags = [line.replace("\r", "") for line in self.run_program_argsasarray("git", ["tag"], repository)[1].split("\n") if len(line) > 0]
509
+ tags = [line.replace("\r", "") for line in self.run_program_argsasarray(
510
+ "git", ["tag"], repository)[1].split("\n") if len(line) > 0]
451
511
  return tags
452
512
 
453
513
  @GeneralUtilities.check_arguments
@@ -457,43 +517,53 @@ class ScriptCollectionCore:
457
517
  counter = 0
458
518
  for tag in tags:
459
519
  counter = counter+1
460
- GeneralUtilities.write_message_to_stdout(f"Process tag {counter}/{tags_count}.")
461
- if self.git_commit_is_ancestor(repository, tag, tag_source_branch): # tag is on source-branch
520
+ GeneralUtilities.write_message_to_stdout(
521
+ f"Process tag {counter}/{tags_count}.")
522
+ # tag is on source-branch
523
+ if self.git_commit_is_ancestor(repository, tag, tag_source_branch):
462
524
  commit_id_old = self.git_get_commitid_of_tag(repository, tag)
463
- commit_date: datetime = self.git_get_commit_date(repository, commit_id_old)
525
+ commit_date: datetime = self.git_get_commit_date(
526
+ repository, commit_id_old)
464
527
  date_as_string = self.__datetime_to_string_for_git(commit_date)
465
- search_commit_result = self.run_program_argsasarray("git", ["log", f'--after="{date_as_string}"', f'--before="{date_as_string}"', "--pretty=format:%H", tag_target_branch], repository, throw_exception_if_exitcode_is_not_zero=False)
528
+ search_commit_result = self.run_program_argsasarray("git", ["log", f'--after="{date_as_string}"', f'--before="{date_as_string}"',
529
+ "--pretty=format:%H", tag_target_branch], repository, throw_exception_if_exitcode_is_not_zero=False)
466
530
  if search_commit_result[0] != 0 or not GeneralUtilities.string_has_nonwhitespace_content(search_commit_result[1]):
467
- raise ValueError(f"Can not calculate corresponding commit for tag '{tag}'.")
531
+ raise ValueError(
532
+ f"Can not calculate corresponding commit for tag '{tag}'.")
468
533
  commit_id_new = search_commit_result[1]
469
534
  self.git_delete_tag(repository, tag)
470
- self.git_create_tag(repository, commit_id_new, tag, sign, message)
535
+ self.git_create_tag(
536
+ repository, commit_id_new, tag, sign, message)
471
537
 
472
538
  @GeneralUtilities.check_arguments
473
539
  def get_current_git_branch_has_tag(self, repository_folder: str) -> bool:
474
- result = self.run_program_argsasarray("git", ["describe", "--tags", "--abbrev=0"], repository_folder, verbosity=0, throw_exception_if_exitcode_is_not_zero=False)
540
+ result = self.run_program_argsasarray(
541
+ "git", ["describe", "--tags", "--abbrev=0"], repository_folder, verbosity=0, throw_exception_if_exitcode_is_not_zero=False)
475
542
  return result[0] == 0
476
543
 
477
544
  @GeneralUtilities.check_arguments
478
545
  def get_latest_git_tag(self, repository_folder: str) -> str:
479
- result = self.run_program_argsasarray("git", ["describe", "--tags", "--abbrev=0"], repository_folder, verbosity=0)
546
+ result = self.run_program_argsasarray(
547
+ "git", ["describe", "--tags", "--abbrev=0"], repository_folder, verbosity=0)
480
548
  result = result[1].replace("\r", "").replace("\n", "")
481
549
  return result
482
550
 
483
551
  @GeneralUtilities.check_arguments
484
552
  def get_staged_or_committed_git_ignored_files(self, repository_folder: str) -> list[str]:
485
- tresult = self.run_program_argsasarray("git", ["ls-files", "-i", "-c", "--exclude-standard"], repository_folder, verbosity=0)
553
+ tresult = self.run_program_argsasarray(
554
+ "git", ["ls-files", "-i", "-c", "--exclude-standard"], repository_folder, verbosity=0)
486
555
  tresult = tresult[1].replace("\r", "")
487
- result=[line for line in tresult.split("\n") if len(line)>0]
556
+ result = [line for line in tresult.split("\n") if len(line) > 0]
488
557
  return result
489
558
 
490
559
  @GeneralUtilities.check_arguments
491
- def git_repository_has_commits(self,repository_folder: str) -> bool:
492
- return self.run_program_argsasarray("git",["rev-parse","--verify","HEAD"],repository_folder,throw_exception_if_exitcode_is_not_zero=False)[0]==0
560
+ def git_repository_has_commits(self, repository_folder: str) -> bool:
561
+ return self.run_program_argsasarray("git", ["rev-parse", "--verify", "HEAD"], repository_folder, throw_exception_if_exitcode_is_not_zero=False)[0] == 0
493
562
 
494
563
  @GeneralUtilities.check_arguments
495
564
  def export_filemetadata(self, folder: str, target_file: str, encoding: str = "utf-8", filter_function=None) -> None:
496
- folder = GeneralUtilities.resolve_relative_path_from_current_working_directory(folder)
565
+ folder = GeneralUtilities.resolve_relative_path_from_current_working_directory(
566
+ folder)
497
567
  lines = list()
498
568
  path_prefix = len(folder)+1
499
569
  items = dict()
@@ -504,10 +574,12 @@ class ScriptCollectionCore:
504
574
  for file_or_folder, item_type in items.items():
505
575
  truncated_file = file_or_folder[path_prefix:]
506
576
  if (filter_function is None or filter_function(folder, truncated_file)):
507
- owner_and_permisssion = self.get_file_owner_and_file_permission(file_or_folder)
577
+ owner_and_permisssion = self.get_file_owner_and_file_permission(
578
+ file_or_folder)
508
579
  user = owner_and_permisssion[0]
509
580
  permissions = owner_and_permisssion[1]
510
- lines.append(f"{truncated_file};{item_type};{user};{permissions}")
581
+ lines.append(
582
+ f"{truncated_file};{item_type};{user};{permissions}")
511
583
  lines = sorted(lines, key=str.casefold)
512
584
  with open(target_file, "w", encoding=encoding) as file_object:
513
585
  file_object.write("\n".join(lines))
@@ -527,12 +599,14 @@ class ScriptCollectionCore:
527
599
  foldername = os.path.basename(subfolder)
528
600
  if ".git" in foldername:
529
601
  new_name = foldername.replace(".git", ".gitx")
530
- subfolder2 = os.path.join(str(Path(subfolder).parent), new_name)
602
+ subfolder2 = os.path.join(
603
+ str(Path(subfolder).parent), new_name)
531
604
  os.rename(subfolder, subfolder2)
532
605
  renamed_items[subfolder2] = subfolder
533
606
  else:
534
607
  subfolder2 = subfolder
535
- self.__escape_git_repositories_in_folder_internal(subfolder2, renamed_items)
608
+ self.__escape_git_repositories_in_folder_internal(
609
+ subfolder2, renamed_items)
536
610
  return renamed_items
537
611
 
538
612
  def deescape_git_repositories_in_folder(self, renamed_items: dict[str, str]):
@@ -554,14 +628,17 @@ class ScriptCollectionCore:
554
628
  lines.sort(key=self.__sort_fmd)
555
629
  for line in lines:
556
630
  splitted: list = line.split(";")
557
- full_path_of_file_or_folder: str = os.path.join(folder, splitted[0])
631
+ full_path_of_file_or_folder: str = os.path.join(
632
+ folder, splitted[0])
558
633
  filetype: str = splitted[1]
559
634
  user: str = splitted[2]
560
635
  permissions: str = splitted[3]
561
636
  if filetype == "d" and create_folder_is_not_exist and not os.path.isdir(full_path_of_file_or_folder):
562
- GeneralUtilities.ensure_directory_exists(full_path_of_file_or_folder)
637
+ GeneralUtilities.ensure_directory_exists(
638
+ full_path_of_file_or_folder)
563
639
  if (filetype == "f" and os.path.isfile(full_path_of_file_or_folder)) or (filetype == "d" and os.path.isdir(full_path_of_file_or_folder)):
564
- self.set_owner(full_path_of_file_or_folder, user, os.name != 'nt')
640
+ self.set_owner(full_path_of_file_or_folder,
641
+ user, os.name != 'nt')
565
642
  self.set_permission(full_path_of_file_or_folder, permissions)
566
643
  else:
567
644
  if strict:
@@ -569,27 +646,34 @@ class ScriptCollectionCore:
569
646
  filetype_full = "File"
570
647
  if filetype == "d":
571
648
  filetype_full = "Directory"
572
- raise ValueError(f"{filetype_full} '{full_path_of_file_or_folder}' does not exist")
649
+ raise ValueError(
650
+ f"{filetype_full} '{full_path_of_file_or_folder}' does not exist")
573
651
 
574
652
  @GeneralUtilities.check_arguments
575
653
  def __calculate_lengh_in_seconds(self, filename: str, folder: str) -> float:
576
- argument = ['-v', 'error', '-show_entries', 'format=duration', '-of', 'default=noprint_wrappers=1:nokey=1', filename]
577
- result = self.run_program_argsasarray("ffprobe", argument, folder, throw_exception_if_exitcode_is_not_zero=True)
654
+ argument = ['-v', 'error', '-show_entries', 'format=duration',
655
+ '-of', 'default=noprint_wrappers=1:nokey=1', filename]
656
+ result = self.run_program_argsasarray(
657
+ "ffprobe", argument, folder, throw_exception_if_exitcode_is_not_zero=True)
578
658
  return float(result[1].replace('\n', ''))
579
659
 
580
660
  @GeneralUtilities.check_arguments
581
661
  def __create_thumbnails(self, filename: str, fps: str, folder: str, tempname_for_thumbnails: str) -> None:
582
- argument = ['-i', filename, '-r', str(fps), '-vf', 'scale=-1:120', '-vcodec', 'png', f'{tempname_for_thumbnails}-%002d.png']
583
- self.run_program_argsasarray("ffmpeg", argument, folder, throw_exception_if_exitcode_is_not_zero=True)
662
+ argument = ['-i', filename, '-r', str(fps), '-vf', 'scale=-1:120',
663
+ '-vcodec', 'png', f'{tempname_for_thumbnails}-%002d.png']
664
+ self.run_program_argsasarray(
665
+ "ffmpeg", argument, folder, throw_exception_if_exitcode_is_not_zero=True)
584
666
 
585
667
  @GeneralUtilities.check_arguments
586
668
  def __create_thumbnail(self, outputfilename: str, folder: str, length_in_seconds: float, tempname_for_thumbnails: str, amount_of_images: int) -> None:
587
669
  duration = timedelta(seconds=length_in_seconds)
588
670
  info = GeneralUtilities.timedelta_to_simple_string(duration)
589
- next_square_number = str(int(math.sqrt(GeneralUtilities.get_next_square_number(amount_of_images))))
671
+ next_square_number = str(
672
+ int(math.sqrt(GeneralUtilities.get_next_square_number(amount_of_images))))
590
673
  argument = ['-title', f'"{outputfilename} ({info})"', '-tile', f'{next_square_number}x{next_square_number}',
591
674
  f'{tempname_for_thumbnails}*.png', f'{outputfilename}.png']
592
- self.run_program_argsasarray("montage", argument, folder, throw_exception_if_exitcode_is_not_zero=True)
675
+ self.run_program_argsasarray(
676
+ "montage", argument, folder, throw_exception_if_exitcode_is_not_zero=True)
593
677
 
594
678
  @GeneralUtilities.check_arguments
595
679
  def roundup(self, x: float, places: int) -> int:
@@ -604,13 +688,15 @@ class ScriptCollectionCore:
604
688
  if tempname_for_thumbnails is None:
605
689
  tempname_for_thumbnails = "t"+str(uuid.uuid4())
606
690
 
607
- file = GeneralUtilities.resolve_relative_path_from_current_working_directory(file)
691
+ file = GeneralUtilities.resolve_relative_path_from_current_working_directory(
692
+ file)
608
693
  filename = os.path.basename(file)
609
694
  folder = os.path.dirname(file)
610
695
  filename_without_extension = Path(file).stem
611
696
 
612
697
  try:
613
- length_in_seconds = self.__calculate_lengh_in_seconds(filename, folder)
698
+ length_in_seconds = self.__calculate_lengh_in_seconds(
699
+ filename, folder)
614
700
  if (frames_per_second.endswith("fps")):
615
701
  # frames per second, example: frames_per_second="20fps" => 20 frames per second
616
702
  x = self.roundup(float(frames_per_second[:-3]), 2)
@@ -619,9 +705,12 @@ class ScriptCollectionCore:
619
705
  else:
620
706
  # concrete amount of frame, examples: frames_per_second="16" => 16 frames for entire video
621
707
  amounf_of_previewframes = int(float(frames_per_second))
622
- frames_per_secondx = f"{amounf_of_previewframes-2}/{length_in_seconds}" # self.roundup((amounf_of_previewframes-2)/length_in_seconds, 2)
623
- self.__create_thumbnails(filename, frames_per_secondx, folder, tempname_for_thumbnails)
624
- self.__create_thumbnail(filename_without_extension, folder, length_in_seconds, tempname_for_thumbnails, amounf_of_previewframes)
708
+ # self.roundup((amounf_of_previewframes-2)/length_in_seconds, 2)
709
+ frames_per_secondx = f"{amounf_of_previewframes-2}/{length_in_seconds}"
710
+ self.__create_thumbnails(
711
+ filename, frames_per_secondx, folder, tempname_for_thumbnails)
712
+ self.__create_thumbnail(filename_without_extension, folder,
713
+ length_in_seconds, tempname_for_thumbnails, amounf_of_previewframes)
625
714
  finally:
626
715
  for thumbnail_to_delete in Path(folder).rglob(tempname_for_thumbnails+"-*"):
627
716
  file = str(thumbnail_to_delete)
@@ -701,13 +790,16 @@ class ScriptCollectionCore:
701
790
 
702
791
  @GeneralUtilities.check_arguments
703
792
  def SCCreateSimpleMergeWithoutRelease(self, repository: str, sourcebranch: str, targetbranch: str, remotename: str, remove_source_branch: bool) -> None:
704
- commitid = self.git_merge(repository, sourcebranch, targetbranch, False, True)
793
+ commitid = self.git_merge(
794
+ repository, sourcebranch, targetbranch, False, True)
705
795
  self.git_merge(repository, targetbranch, sourcebranch, True, True)
706
796
  created_version = self.get_semver_version_from_gitversion(repository)
707
797
  self.git_create_tag(repository, commitid, f"v{created_version}", True)
708
- self.git_push(repository, remotename, targetbranch, targetbranch, False, True)
798
+ self.git_push(repository, remotename, targetbranch,
799
+ targetbranch, False, True)
709
800
  if (GeneralUtilities.string_has_nonwhitespace_content(remotename)):
710
- self.git_push(repository, remotename, sourcebranch, sourcebranch, False, True)
801
+ self.git_push(repository, remotename, sourcebranch,
802
+ sourcebranch, False, True)
711
803
  if (remove_source_branch):
712
804
  self.git_remove_branch(repository, sourcebranch)
713
805
 
@@ -739,7 +831,8 @@ class ScriptCollectionCore:
739
831
 
740
832
  # sort lines if desired
741
833
  if sort:
742
- lines = sorted(lines, key=lambda singleline: self.__adapt_line_for_sorting(singleline, ignored_start_character))
834
+ lines = sorted(lines, key=lambda singleline: self.__adapt_line_for_sorting(
835
+ singleline, ignored_start_character))
743
836
 
744
837
  # reinsert first line
745
838
  if ignore_first_line:
@@ -750,7 +843,8 @@ class ScriptCollectionCore:
750
843
 
751
844
  return 0
752
845
  else:
753
- GeneralUtilities.write_message_to_stdout(f"File '{file}' does not exist")
846
+ GeneralUtilities.write_message_to_stdout(
847
+ f"File '{file}' does not exist")
754
848
  return 1
755
849
 
756
850
  @GeneralUtilities.check_arguments
@@ -779,7 +873,8 @@ class ScriptCollectionCore:
779
873
 
780
874
  @GeneralUtilities.check_arguments
781
875
  def __process_file(self, file: str, substringInFilename: str, newSubstringInFilename: str, conflictResolveMode: str) -> None:
782
- new_filename = os.path.join(os.path.dirname(file), os.path.basename(file).replace(substringInFilename, newSubstringInFilename))
876
+ new_filename = os.path.join(os.path.dirname(file), os.path.basename(
877
+ file).replace(substringInFilename, newSubstringInFilename))
783
878
  if file != new_filename:
784
879
  if os.path.isfile(new_filename):
785
880
  if filecmp.cmp(file, new_filename):
@@ -804,12 +899,14 @@ class ScriptCollectionCore:
804
899
  @GeneralUtilities.check_arguments
805
900
  def SCReplaceSubstringsInFilenames(self, folder: str, substringInFilename: str, newSubstringInFilename: str, conflictResolveMode: str) -> None:
806
901
  for file in GeneralUtilities.absolute_file_paths(folder):
807
- self.__process_file(file, substringInFilename, newSubstringInFilename, conflictResolveMode)
902
+ self.__process_file(file, substringInFilename,
903
+ newSubstringInFilename, conflictResolveMode)
808
904
 
809
905
  @GeneralUtilities.check_arguments
810
906
  def __check_file(self, file: str, searchstring: str) -> None:
811
907
  bytes_ascii = bytes(searchstring, "ascii")
812
- bytes_utf16 = bytes(searchstring, "utf-16") # often called "unicode-encoding"
908
+ # often called "unicode-encoding"
909
+ bytes_utf16 = bytes(searchstring, "utf-16")
813
910
  bytes_utf8 = bytes(searchstring, "utf-8")
814
911
  with open(file, mode='rb') as file_object:
815
912
  content = file_object.read()
@@ -828,7 +925,8 @@ class ScriptCollectionCore:
828
925
  @GeneralUtilities.check_arguments
829
926
  def __print_qr_code_by_csv_line(self, displayname: str, website: str, emailaddress: str, key: str, period: str) -> None:
830
927
  qrcode_content = f"otpauth://totp/{website}:{emailaddress}?secret={key}&issuer={displayname}&period={period}"
831
- GeneralUtilities.write_message_to_stdout(f"{displayname} ({emailaddress}):")
928
+ GeneralUtilities.write_message_to_stdout(
929
+ f"{displayname} ({emailaddress}):")
832
930
  GeneralUtilities.write_message_to_stdout(qrcode_content)
833
931
  qr = qrcode.QRCode()
834
932
  qr.add_data(qrcode_content)
@@ -844,29 +942,35 @@ class ScriptCollectionCore:
844
942
  lines.sort(key=lambda items: ''.join(items).lower())
845
943
  for line in lines:
846
944
  GeneralUtilities.write_message_to_stdout(separator_line)
847
- self.__print_qr_code_by_csv_line(line[0], line[1], line[2], line[3], line[4])
945
+ self.__print_qr_code_by_csv_line(
946
+ line[0], line[1], line[2], line[3], line[4])
848
947
  GeneralUtilities.write_message_to_stdout(separator_line)
849
948
 
850
949
  @GeneralUtilities.check_arguments
851
950
  def SCUploadFileToFileHost(self, file: str, host: str) -> int:
852
951
  try:
853
- GeneralUtilities.write_message_to_stdout(self.upload_file_to_file_host(file, host))
952
+ GeneralUtilities.write_message_to_stdout(
953
+ self.upload_file_to_file_host(file, host))
854
954
  return 0
855
955
  except Exception as exception:
856
- GeneralUtilities.write_exception_to_stderr_with_traceback(exception, traceback)
956
+ GeneralUtilities.write_exception_to_stderr_with_traceback(
957
+ exception, traceback)
857
958
  return 1
858
959
 
859
960
  @GeneralUtilities.check_arguments
860
961
  def SCFileIsAvailableOnFileHost(self, file: str) -> int:
861
962
  try:
862
963
  if self.file_is_available_on_file_host(file):
863
- GeneralUtilities.write_message_to_stdout(f"'{file}' is available")
964
+ GeneralUtilities.write_message_to_stdout(
965
+ f"'{file}' is available")
864
966
  return 0
865
967
  else:
866
- GeneralUtilities.write_message_to_stdout(f"'{file}' is not available")
968
+ GeneralUtilities.write_message_to_stdout(
969
+ f"'{file}' is not available")
867
970
  return 1
868
971
  except Exception as exception:
869
- GeneralUtilities.write_exception_to_stderr_with_traceback(exception, traceback)
972
+ GeneralUtilities.write_exception_to_stderr_with_traceback(
973
+ exception, traceback)
870
974
  return 2
871
975
 
872
976
  @GeneralUtilities.check_arguments
@@ -878,7 +982,8 @@ class ScriptCollectionCore:
878
982
  # timestamp: "51eb505a"
879
983
  # target: "c1910018"
880
984
  # nonce: "de19b302"
881
- header = str(block_version_number + previousblockhash + transactionsmerkleroot + timestamp + target + nonce)
985
+ header = str(block_version_number + previousblockhash +
986
+ transactionsmerkleroot + timestamp + target + nonce)
882
987
  return binascii.hexlify(hashlib.sha256(hashlib.sha256(binascii.unhexlify(header)).digest()).digest()[::-1]).decode('utf-8')
883
988
 
884
989
  @GeneralUtilities.check_arguments
@@ -918,11 +1023,14 @@ class ScriptCollectionCore:
918
1023
  full_path = os.path.join(root, file)
919
1024
  with (open(full_path, "rb").read()) as text_io_wrapper:
920
1025
  content = text_io_wrapper
921
- path_in_iso = '/' + files_directory + self.__adjust_folder_name(full_path[len(folder)::1]).upper()
1026
+ path_in_iso = '/' + files_directory + \
1027
+ self.__adjust_folder_name(
1028
+ full_path[len(folder)::1]).upper()
922
1029
  if path_in_iso not in created_directories:
923
1030
  iso.add_directory(path_in_iso)
924
1031
  created_directories.append(path_in_iso)
925
- iso.add_fp(BytesIO(content), len(content), path_in_iso + '/' + file.upper() + ';1')
1032
+ iso.add_fp(BytesIO(content), len(content),
1033
+ path_in_iso + '/' + file.upper() + ';1')
926
1034
  iso.write(iso_file)
927
1035
  iso.close()
928
1036
 
@@ -932,8 +1040,10 @@ class ScriptCollectionCore:
932
1040
  namemappingfile = "name_map.csv"
933
1041
  files_directory = inputfolder
934
1042
  files_directory_obf = f"{files_directory}_Obfuscated"
935
- self.SCObfuscateFilesFolder(inputfolder, printtableheadline, namemappingfile, extensions)
936
- os.rename(namemappingfile, os.path.join(files_directory_obf, namemappingfile))
1043
+ self.SCObfuscateFilesFolder(
1044
+ inputfolder, printtableheadline, namemappingfile, extensions)
1045
+ os.rename(namemappingfile, os.path.join(
1046
+ files_directory_obf, namemappingfile))
937
1047
  if createisofile:
938
1048
  self.__create_iso(files_directory_obf, outputfile)
939
1049
  shutil.rmtree(files_directory_obf)
@@ -947,13 +1057,15 @@ class ScriptCollectionCore:
947
1057
  obfuscate_file_extensions = extensions.split(",")
948
1058
 
949
1059
  if (os.path.isdir(inputfolder)):
950
- printtableheadline = GeneralUtilities.string_to_boolean(printtableheadline)
1060
+ printtableheadline = GeneralUtilities.string_to_boolean(
1061
+ printtableheadline)
951
1062
  files = []
952
1063
  if not os.path.isfile(namemappingfile):
953
1064
  with open(namemappingfile, "a", encoding="utf-8"):
954
1065
  pass
955
1066
  if printtableheadline:
956
- GeneralUtilities.append_line_to_file(namemappingfile, "Original filename;new filename;SHA2-hash of file")
1067
+ GeneralUtilities.append_line_to_file(
1068
+ namemappingfile, "Original filename;new filename;SHA2-hash of file")
957
1069
  for file in GeneralUtilities.absolute_file_paths(inputfolder):
958
1070
  if os.path.isfile(os.path.join(inputfolder, file)):
959
1071
  if obfuscate_all_files or self.__extension_matchs(file, obfuscate_file_extensions):
@@ -962,9 +1074,11 @@ class ScriptCollectionCore:
962
1074
  hash_value = GeneralUtilities.get_sha256_of_file(file)
963
1075
  extension = Path(file).suffix
964
1076
  new_file_name_without_path = str(uuid.uuid4())[0:8] + extension
965
- new_file_name = os.path.join(os.path.dirname(file), new_file_name_without_path)
1077
+ new_file_name = os.path.join(
1078
+ os.path.dirname(file), new_file_name_without_path)
966
1079
  os.rename(file, new_file_name)
967
- GeneralUtilities.append_line_to_file(namemappingfile, os.path.basename(file) + ";" + new_file_name_without_path + ";" + hash_value)
1080
+ GeneralUtilities.append_line_to_file(namemappingfile, os.path.basename(
1081
+ file) + ";" + new_file_name_without_path + ";" + hash_value)
968
1082
  else:
969
1083
  raise ValueError(f"Directory not found: '{inputfolder}'")
970
1084
 
@@ -981,12 +1095,15 @@ class ScriptCollectionCore:
981
1095
  for line in reversed(lines):
982
1096
  if not GeneralUtilities.string_is_none_or_whitespace(line):
983
1097
  if "RunningHealthy (" in line: # TODO use regex
984
- GeneralUtilities.write_message_to_stderr(f"Healthy running due to line '{line}' in file '{file}'.")
1098
+ GeneralUtilities.write_message_to_stderr(
1099
+ f"Healthy running due to line '{line}' in file '{file}'.")
985
1100
  return 0
986
1101
  else:
987
- GeneralUtilities.write_message_to_stderr(f"Not healthy running due to line '{line}' in file '{file}'.")
1102
+ GeneralUtilities.write_message_to_stderr(
1103
+ f"Not healthy running due to line '{line}' in file '{file}'.")
988
1104
  return 1
989
- GeneralUtilities.write_message_to_stderr(f"No valid line found for healthycheck in file '{file}'.")
1105
+ GeneralUtilities.write_message_to_stderr(
1106
+ f"No valid line found for healthycheck in file '{file}'.")
990
1107
  return 2
991
1108
 
992
1109
  @GeneralUtilities.check_arguments
@@ -1006,7 +1123,8 @@ class ScriptCollectionCore:
1006
1123
  self.SCChangeHashOfProgram(file)
1007
1124
  os.remove(file)
1008
1125
  os.rename(file + ".modified", file)
1009
- self.SCFilenameObfuscator(inputfolder, printtableheadline, namemappingfile, extensions)
1126
+ self.SCFilenameObfuscator(
1127
+ inputfolder, printtableheadline, namemappingfile, extensions)
1010
1128
  else:
1011
1129
  raise ValueError(f"Directory not found: '{inputfolder}'")
1012
1130
 
@@ -1022,10 +1140,13 @@ class ScriptCollectionCore:
1022
1140
  package_url: str = f"https://deb.torproject.org/torproject.org/dists/{debian_version}/main/binary-amd64/Packages"
1023
1141
  r = requests.get(package_url, timeout=5)
1024
1142
  if r.status_code != 200:
1025
- raise ValueError(f"Checking for latest tor package resulted in HTTP-response-code {r.status_code}.")
1026
- lines = GeneralUtilities.string_to_lines(GeneralUtilities.bytes_to_string(r.content))
1143
+ raise ValueError(
1144
+ f"Checking for latest tor package resulted in HTTP-response-code {r.status_code}.")
1145
+ lines = GeneralUtilities.string_to_lines(
1146
+ GeneralUtilities.bytes_to_string(r.content))
1027
1147
  version_line_prefix = "Version: "
1028
- version_content_line = [line for line in lines if line.startswith(version_line_prefix)][1]
1148
+ version_content_line = [
1149
+ line for line in lines if line.startswith(version_line_prefix)][1]
1029
1150
  version_with_overhead = version_content_line[len(version_line_prefix):]
1030
1151
  tor_version = version_with_overhead.split("~")[0]
1031
1152
  return tor_version
@@ -1071,10 +1192,13 @@ class ScriptCollectionCore:
1071
1192
  def run_testcases_for_python_project(self, repository_folder: str):
1072
1193
  self.run_program("coverage", "run -m pytest", repository_folder)
1073
1194
  self.run_program("coverage", "xml", repository_folder)
1074
- GeneralUtilities.ensure_directory_exists(os.path.join(repository_folder, "Other/TestCoverage"))
1075
- coveragefile = os.path.join(repository_folder, "Other/TestCoverage/TestCoverage.xml")
1195
+ GeneralUtilities.ensure_directory_exists(
1196
+ os.path.join(repository_folder, "Other/TestCoverage"))
1197
+ coveragefile = os.path.join(
1198
+ repository_folder, "Other/TestCoverage/TestCoverage.xml")
1076
1199
  GeneralUtilities.ensure_file_does_not_exist(coveragefile)
1077
- os.rename(os.path.join(repository_folder, "coverage.xml"), coveragefile)
1200
+ os.rename(os.path.join(repository_folder,
1201
+ "coverage.xml"), coveragefile)
1078
1202
 
1079
1203
  @GeneralUtilities.check_arguments
1080
1204
  def get_file_permission(self, file: str) -> str:
@@ -1110,7 +1234,8 @@ class ScriptCollectionCore:
1110
1234
  splitted = ' '.join(ls_output.split()).split(' ')
1111
1235
  return f"{splitted[2]}:{splitted[3]}"
1112
1236
  except Exception as exception:
1113
- raise ValueError(f"ls-output '{ls_output}' not parsable") from exception
1237
+ raise ValueError(
1238
+ f"ls-output '{ls_output}' not parsable") from exception
1114
1239
 
1115
1240
  @GeneralUtilities.check_arguments
1116
1241
  def get_file_owner_and_file_permission(self, file: str) -> str:
@@ -1120,10 +1245,13 @@ class ScriptCollectionCore:
1120
1245
  @GeneralUtilities.check_arguments
1121
1246
  def __ls(self, file: str) -> str:
1122
1247
  file = file.replace("\\", "/")
1123
- GeneralUtilities.assert_condition(os.path.isfile(file) or os.path.isdir(file), f"Can not execute 'ls' because '{file}' does not exist")
1248
+ GeneralUtilities.assert_condition(os.path.isfile(file) or os.path.isdir(
1249
+ file), f"Can not execute 'ls' because '{file}' does not exist")
1124
1250
  result = self.run_program_argsasarray("ls", ["-ld", file])
1125
- GeneralUtilities.assert_condition(result[0] == 0, f"'ls -ld {file}' resulted in exitcode {str(result[0])}. StdErr: {result[2]}")
1126
- GeneralUtilities.assert_condition(not GeneralUtilities.string_is_none_or_whitespace(result[1]), f"'ls' of '{file}' had an empty output. StdErr: '{result[2]}'")
1251
+ GeneralUtilities.assert_condition(
1252
+ result[0] == 0, f"'ls -ld {file}' resulted in exitcode {str(result[0])}. StdErr: {result[2]}")
1253
+ GeneralUtilities.assert_condition(not GeneralUtilities.string_is_none_or_whitespace(
1254
+ result[1]), f"'ls' of '{file}' had an empty output. StdErr: '{result[2]}'")
1127
1255
  return result[1]
1128
1256
 
1129
1257
  @GeneralUtilities.check_arguments
@@ -1151,7 +1279,7 @@ class ScriptCollectionCore:
1151
1279
  # <run programs>
1152
1280
 
1153
1281
  @GeneralUtilities.check_arguments
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:
1282
+ 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, interactive: bool = False) -> Popen:
1155
1283
  # Verbosity:
1156
1284
  # 0=Quiet (No output will be printed.)
1157
1285
  # 1=Normal (If the exitcode of the executed program is not 0 then the StdErr will be printed.)
@@ -1174,16 +1302,24 @@ class ScriptCollectionCore:
1174
1302
  GeneralUtilities.write_message_to_stdout(f"Run '{info_for_log}'.")
1175
1303
 
1176
1304
  if isinstance(self.program_runner, ProgramRunnerEpew):
1177
- custom_argument = CustomEpewArgument(print_errors_as_information, log_file, timeoutInSeconds, addLogOverhead, title, log_namespace, verbosity, arguments_for_log)
1178
- popen: Popen = self.program_runner.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument)
1305
+ custom_argument = CustomEpewArgument(
1306
+ print_errors_as_information, log_file, timeoutInSeconds, addLogOverhead, title, log_namespace, verbosity, arguments_for_log)
1307
+ popen: Popen = self.program_runner.run_program_argsasarray_async_helper(
1308
+ program, arguments_as_array, working_directory, custom_argument, interactive)
1179
1309
  return popen
1180
1310
 
1181
1311
  # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
1182
1312
 
1183
1313
  @GeneralUtilities.check_arguments
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]:
1314
+ 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, interactive: bool = False) -> tuple[int, str, str, int]:
1315
+ # verbosity 1: No output will be logged.
1316
+ # verbosity 2: If the exitcode of the executed program is not 0 then the StdErr will be logged. This is supposed to be the default verbosity-level.
1317
+ # verbosity 3: Logs and prints StdOut and StdErr of the executed program in realtime.
1318
+ # verbosity 4: Same as loglevel 3 but with some more overhead-information.
1185
1319
  try:
1186
- mock_loader_result = self.__try_load_mock(program, ' '.join(arguments_as_array), working_directory)
1320
+ arguments_as_str = ' '.join(arguments_as_array)
1321
+ mock_loader_result = self.__try_load_mock(
1322
+ program, arguments_as_str, working_directory)
1187
1323
  if mock_loader_result[0]:
1188
1324
  return mock_loader_result[1]
1189
1325
 
@@ -1192,83 +1328,137 @@ class ScriptCollectionCore:
1192
1328
 
1193
1329
  arguments_for_exception_as_string = ' '.join(arguments_for_log)
1194
1330
 
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)
1331
+ arguments_for_log_as_string = ' '.join(arguments_for_log)
1332
+ cmd = f'{working_directory}>{program} {arguments_for_log_as_string}'
1241
1333
 
1334
+ if GeneralUtilities.string_is_none_or_whitespace(title):
1335
+ info_for_log = cmd
1336
+ else:
1337
+ info_for_log = title
1338
+
1339
+ if verbosity >= 3:
1340
+ GeneralUtilities.write_message_to_stdout(f"Run '{info_for_log}'.")
1341
+
1342
+ 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:
1343
+ pid = process.pid
1344
+
1345
+ stdout_lines = list[str]()
1346
+ stderr_lines = list[str]()
1347
+
1348
+ live_console_output_printing = 2 < verbosity and interactive
1349
+
1350
+ log_to_file = log_file is not None
1351
+ if log_to_file:
1352
+ GeneralUtilities.ensure_file_exists(log_file)
1353
+
1354
+ if interactive:
1355
+ # there are 2 issues in this part:
1356
+ # 1.: ctrl+c
1357
+ # 2.: sometimes this function does not terminate even if the started process exited
1358
+ def stream_process(process) -> bool:
1359
+ try:
1360
+ go: bool = process.poll() is None
1361
+
1362
+ stdoutreader: BufferedReader = process.stdout
1363
+ if stdoutreader.readable():
1364
+ stdoutresultb: bytes = stdoutreader.read()
1365
+ stdoutresult = GeneralUtilities.bytes_to_string(
1366
+ stdoutresultb)
1367
+ stdoutlines = GeneralUtilities.string_to_lines(
1368
+ stdoutresult)
1369
+ for line in stdoutlines:
1370
+ line_stripped = line.replace(
1371
+ "\r", "").strip()
1372
+ if len(line_stripped) > 0:
1373
+ line_str = line_stripped
1374
+ stdout_lines.append(line_str)
1375
+ if live_console_output_printing:
1376
+ GeneralUtilities.write_message_to_stdout(
1377
+ line_str)
1378
+ if log_to_file:
1379
+ GeneralUtilities.append_line_to_file(
1380
+ log_file, line_str)
1381
+
1382
+ stderrreader: BufferedReader = process.stderr
1383
+ if stderrreader.readable():
1384
+ stderrresultb: bytes = stderrreader.read()
1385
+ stderrresult = GeneralUtilities.bytes_to_string(
1386
+ stderrresultb)
1387
+ stderrlines = GeneralUtilities.string_to_lines(
1388
+ stderrresult)
1389
+ for line in stderrlines:
1390
+ line_stripped = line.replace(
1391
+ "\r", "").strip()
1392
+ if len(line_stripped) > 0:
1393
+ line_str = line_stripped
1394
+ stderr_lines.append(line_str)
1395
+ if live_console_output_printing:
1396
+ if print_errors_as_information:
1397
+ GeneralUtilities.write_message_to_stdout(
1398
+ line_str)
1399
+ else:
1400
+ GeneralUtilities.write_message_to_stderr(
1401
+ line_str)
1402
+ if log_to_file:
1403
+ GeneralUtilities.append_line_to_file(
1404
+ log_file, line_str)
1405
+
1406
+ return go
1407
+ except Exception:
1408
+ return False
1409
+
1410
+ while stream_process(process):
1411
+ time.sleep(0.1)
1412
+
1413
+ exit_code = process.poll()
1414
+ stdout = '\n'.join(stdout_lines)
1415
+ stderr = '\n'.join(stderr_lines)
1416
+ else:
1417
+ stdout, stderr = process.communicate()
1418
+ exit_code = process.wait()
1419
+ stdout = GeneralUtilities.bytes_to_string(
1420
+ stdout).replace('\r', '')
1421
+ stderr = GeneralUtilities.bytes_to_string(
1422
+ stderr).replace('\r', '')
1423
+
1424
+ if arguments_for_exception_as_string is None:
1425
+ arguments_for_exception_as_string = ' '.join(
1426
+ arguments_as_array)
1427
+ else:
1428
+ arguments_for_exception_as_string = ' '.join(
1429
+ arguments_for_log)
1242
1430
 
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}')")
1431
+ if throw_exception_if_exitcode_is_not_zero and exit_code != 0:
1432
+ arguments_for_exception_as_string = ' '.join(
1433
+ arguments_for_log)
1434
+ raise ValueError(
1435
+ f"Program '{working_directory}>{program} {arguments_for_exception_as_string}' resulted in exitcode {exit_code}. (StdOut: '{stdout}', StdErr: '{stderr}')")
1246
1436
 
1247
- result = (exit_code, stdout, stderr, pid)
1248
- return result
1437
+ result = (exit_code, stdout, stderr, pid)
1438
+ return result
1249
1439
  except Exception as e:
1250
1440
  raise e
1251
1441
 
1252
1442
  # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
1253
1443
  @GeneralUtilities.check_arguments
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)
1444
+ def run_program(self, program: str, arguments: str = "", working_directory: str = None, verbosity: int = 1, print_errors_as_information: bool = False, log_file: str = None, timeoutInSeconds: int = 600, addLogOverhead: bool = False, title: str = None, log_namespace: str = "", arguments_for_log: list[str] = None, throw_exception_if_exitcode_is_not_zero: bool = True, custom_argument: object = None, interactive: bool = False) -> tuple[int, str, str, int]:
1445
+ 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, interactive)
1256
1446
 
1257
1447
  # Return-values program_runner: Pid
1258
1448
  @GeneralUtilities.check_arguments
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:
1260
- mock_loader_result = self.__try_load_mock(program, ' '.join(arguments_as_array), working_directory)
1449
+ 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, interactive: bool = False) -> int:
1450
+ mock_loader_result = self.__try_load_mock(
1451
+ program, ' '.join(arguments_as_array), working_directory)
1261
1452
  if mock_loader_result[0]:
1262
1453
  return mock_loader_result[1]
1263
-
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)
1454
+ process: Popen = self.__run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, verbosity, print_errors_as_information,
1455
+ log_file, timeoutInSeconds, addLogOverhead, title, log_namespace, arguments_for_log, custom_argument, interactive)
1265
1456
  return process.pid
1266
1457
 
1267
1458
  # Return-values program_runner: Pid
1268
1459
  @GeneralUtilities.check_arguments
1269
- def run_program_async(self, program: str, arguments: str = "", working_directory: str = None, verbosity: int = 1,
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)
1460
+ def run_program_async(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, custom_argument: object = None, interactive: bool = False) -> int:
1461
+ 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, interactive)
1272
1462
 
1273
1463
  @GeneralUtilities.check_arguments
1274
1464
  def __try_load_mock(self, program: str, arguments: str, working_directory: str) -> tuple[bool, tuple[int, str, str, int]]:
@@ -1326,7 +1516,8 @@ class ScriptCollectionCore:
1326
1516
  result = mock_call
1327
1517
  break
1328
1518
  if result is None:
1329
- raise LookupError(f"Tried to execute mock-call '{workingdirectory}>{program} {argument}' but no mock-call was defined for that execution")
1519
+ raise LookupError(
1520
+ f"Tried to execute mock-call '{workingdirectory}>{program} {argument}' but no mock-call was defined for that execution")
1330
1521
  else:
1331
1522
  self.__mocked_program_calls.remove(result)
1332
1523
  return (result.exit_code, result.stdout, result.stderr, result.pid)
@@ -1375,7 +1566,8 @@ class ScriptCollectionCore:
1375
1566
 
1376
1567
  @GeneralUtilities.check_arguments
1377
1568
  def check_system_time_with_default_tolerance(self) -> None:
1378
- self.check_system_time(self.__get_default_tolerance_for_system_time_equals_internet_time())
1569
+ self.check_system_time(
1570
+ self.__get_default_tolerance_for_system_time_equals_internet_time())
1379
1571
 
1380
1572
  @GeneralUtilities.check_arguments
1381
1573
  def __get_default_tolerance_for_system_time_equals_internet_time(self) -> timedelta:
@@ -1384,7 +1576,8 @@ class ScriptCollectionCore:
1384
1576
  @GeneralUtilities.check_arguments
1385
1577
  def increment_version(self, input_version: str, increment_major: bool, increment_minor: bool, increment_patch: bool) -> str:
1386
1578
  splitted = input_version.split(".")
1387
- GeneralUtilities.assert_condition(len(splitted) == 3, f"Version '{input_version}' does not have the 'major.minor.patch'-pattern.")
1579
+ GeneralUtilities.assert_condition(len(
1580
+ splitted) == 3, f"Version '{input_version}' does not have the 'major.minor.patch'-pattern.")
1388
1581
  major = int(splitted[0])
1389
1582
  minor = int(splitted[1])
1390
1583
  patch = int(splitted[2])
@@ -1398,17 +1591,20 @@ class ScriptCollectionCore:
1398
1591
 
1399
1592
  @GeneralUtilities.check_arguments
1400
1593
  def get_semver_version_from_gitversion(self, repository_folder: str) -> str:
1401
- if(self.git_repository_has_commits(repository_folder)):
1402
- result = self.get_version_from_gitversion(repository_folder, "MajorMinorPatch")
1594
+ if (self.git_repository_has_commits(repository_folder)):
1595
+ result = self.get_version_from_gitversion(
1596
+ repository_folder, "MajorMinorPatch")
1403
1597
  if self.git_repository_has_uncommitted_changes(repository_folder):
1404
1598
  if self.get_current_git_branch_has_tag(repository_folder):
1405
- id_of_latest_tag = self.git_get_commitid_of_tag(repository_folder, self.get_latest_git_tag(repository_folder))
1599
+ id_of_latest_tag = self.git_get_commitid_of_tag(
1600
+ repository_folder, self.get_latest_git_tag(repository_folder))
1406
1601
  current_commit = self.git_get_commit_id(repository_folder)
1407
1602
  current_commit_is_on_latest_tag = id_of_latest_tag == current_commit
1408
1603
  if current_commit_is_on_latest_tag:
1409
- result = self.increment_version(result, False, False, True)
1604
+ result = self.increment_version(
1605
+ result, False, False, True)
1410
1606
  else:
1411
- result="0.1.0"
1607
+ result = "0.1.0"
1412
1608
  return result
1413
1609
 
1414
1610
  @staticmethod
@@ -1419,8 +1615,10 @@ class ScriptCollectionCore:
1419
1615
  @GeneralUtilities.check_arguments
1420
1616
  def get_version_from_gitversion(self, folder: str, variable: str) -> str:
1421
1617
  # called twice as workaround for issue 1877 in gitversion ( https://github.com/GitTools/GitVersion/issues/1877 )
1422
- result = self.run_program_argsasarray("gitversion", ["/showVariable", variable], folder,verbosity=0)
1423
- result = self.run_program_argsasarray("gitversion", ["/showVariable", variable], folder,verbosity=0)
1618
+ result = self.run_program_argsasarray(
1619
+ "gitversion", ["/showVariable", variable], folder, verbosity=0)
1620
+ result = self.run_program_argsasarray(
1621
+ "gitversion", ["/showVariable", variable], folder, verbosity=0)
1424
1622
  result = GeneralUtilities.strip_new_line_character(result[1])
1425
1623
 
1426
1624
  return result
@@ -1432,7 +1630,8 @@ class ScriptCollectionCore:
1432
1630
  days_until_expire = 1825
1433
1631
  if password is None:
1434
1632
  password = GeneralUtilities.generate_password()
1435
- 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)
1633
+ self.run_program(
1634
+ "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)
1436
1635
 
1437
1636
  @GeneralUtilities.check_arguments
1438
1637
  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:
@@ -1441,10 +1640,14 @@ class ScriptCollectionCore:
1441
1640
  if password is None:
1442
1641
  password = GeneralUtilities.generate_password()
1443
1642
  rsa_key_length = 4096
1444
- self.run_program("openssl", f'genrsa -out {filename}.key {rsa_key_length}', folder)
1445
- self.run_program("openssl", f'req -new -subj /C={subj_c}/ST={subj_st}/L={subj_l}/O={subj_o}/CN={domain}/OU={subj_ou} -x509 -key {filename}.key -out {filename}.unsigned.crt -days {days_until_expire}', folder)
1446
- self.run_program("openssl", f'pkcs12 -export -out {filename}.selfsigned.pfx -password pass:{password} -inkey {filename}.key -in {filename}.unsigned.crt', folder)
1447
- GeneralUtilities.write_text_to_file(os.path.join(folder, f"{filename}.password"), password)
1643
+ self.run_program(
1644
+ "openssl", f'genrsa -out {filename}.key {rsa_key_length}', folder)
1645
+ self.run_program(
1646
+ "openssl", f'req -new -subj /C={subj_c}/ST={subj_st}/L={subj_l}/O={subj_o}/CN={domain}/OU={subj_ou} -x509 -key {filename}.key -out {filename}.unsigned.crt -days {days_until_expire}', folder)
1647
+ self.run_program(
1648
+ "openssl", f'pkcs12 -export -out {filename}.selfsigned.pfx -password pass:{password} -inkey {filename}.key -in {filename}.unsigned.crt', folder)
1649
+ GeneralUtilities.write_text_to_file(
1650
+ os.path.join(folder, f"{filename}.password"), password)
1448
1651
  GeneralUtilities.write_text_to_file(os.path.join(folder, f"{filename}.san.conf"), f"""[ req ]
1449
1652
  default_bits = {rsa_key_length}
1450
1653
  distinguished_name = req_distinguished_name
@@ -1470,7 +1673,8 @@ DNS = {domain}
1470
1673
 
1471
1674
  @GeneralUtilities.check_arguments
1472
1675
  def generate_certificate_sign_request(self, folder: str, domain: str, filename: str, subj_c: str, subj_st: str, subj_l: str, subj_o: str, subj_ou: str) -> None:
1473
- self.run_program("openssl", f'req -new -subj /C={subj_c}/ST={subj_st}/L={subj_l}/O={subj_o}/CN={domain}/OU={subj_ou} -key {filename}.key -out {filename}.csr -config {filename}.san.conf', folder)
1676
+ self.run_program(
1677
+ "openssl", f'req -new -subj /C={subj_c}/ST={subj_st}/L={subj_l}/O={subj_o}/CN={domain}/OU={subj_ou} -key {filename}.key -out {filename}.csr -config {filename}.san.conf', folder)
1474
1678
 
1475
1679
  @GeneralUtilities.check_arguments
1476
1680
  def sign_certificate(self, folder: str, ca_folder: str, ca_name: str, domain: str, filename: str, days_until_expire: int = None) -> None:
@@ -1479,15 +1683,18 @@ DNS = {domain}
1479
1683
  ca = os.path.join(ca_folder, ca_name)
1480
1684
  password_file = os.path.join(folder, f"{filename}.password")
1481
1685
  password = GeneralUtilities.read_text_from_file(password_file)
1482
- 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)
1483
- self.run_program("openssl", f'pkcs12 -export -out {filename}.pfx -inkey {filename}.key -in {filename}.crt -password pass:{password}', folder)
1686
+ self.run_program(
1687
+ "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)
1688
+ self.run_program(
1689
+ "openssl", f'pkcs12 -export -out {filename}.pfx -inkey {filename}.key -in {filename}.crt -password pass:{password}', folder)
1484
1690
 
1485
1691
  @GeneralUtilities.check_arguments
1486
1692
  def update_dependencies_of_python_in_requirementstxt_file(self, file: str, verbosity: int):
1487
1693
  lines = GeneralUtilities.read_lines_from_file(file)
1488
1694
  new_lines = []
1489
1695
  for line in lines:
1490
- new_lines.append(self.__get_updated_line_for_python_requirements(line.strip()))
1696
+ new_lines.append(
1697
+ self.__get_updated_line_for_python_requirements(line.strip()))
1491
1698
  GeneralUtilities.write_lines_to_file(file, new_lines)
1492
1699
 
1493
1700
  @GeneralUtilities.check_arguments
@@ -1500,7 +1707,8 @@ DNS = {domain}
1500
1707
  # (something like "cyclonedx-bom>=3.11.0" for example)
1501
1708
  package = line.split(">")[0]
1502
1709
  operator = ">=" if ">=" in line else ">"
1503
- response = requests.get(f'https://pypi.org/pypi/{package}/json', timeout=5)
1710
+ response = requests.get(
1711
+ f'https://pypi.org/pypi/{package}/json', timeout=5)
1504
1712
  latest_version = response.json()['info']['version']
1505
1713
  return package+operator+latest_version
1506
1714
  except:
@@ -1531,14 +1739,18 @@ DNS = {domain}
1531
1739
  def update_dependencies_of_dotnet_project(self, csproj_file: str, verbosity: int):
1532
1740
  folder = os.path.dirname(csproj_file)
1533
1741
  csproj_filename = os.path.basename(csproj_file)
1534
- GeneralUtilities.write_message_to_stderr(f"Check for updates in {csproj_filename}")
1535
- result = self.run_program("dotnet", f"list {csproj_filename} package --outdated", folder)
1742
+ GeneralUtilities.write_message_to_stderr(
1743
+ f"Check for updates in {csproj_filename}")
1744
+ result = self.run_program(
1745
+ "dotnet", f"list {csproj_filename} package --outdated", folder)
1536
1746
  for line in result[1].replace("\r", "").split("\n"):
1537
1747
  # Relevant output-lines are something like " > NJsonSchema 10.7.0 10.7.0 10.9.0"
1538
1748
  if ">" in line:
1539
1749
  package_name = line.replace(">", "").strip().split(" ")[0]
1540
- GeneralUtilities.write_message_to_stderr(f"Update package {package_name}")
1541
- self.run_program("dotnet", f"add {csproj_filename} package {package_name}", folder)
1750
+ GeneralUtilities.write_message_to_stderr(
1751
+ f"Update package {package_name}")
1752
+ self.run_program(
1753
+ "dotnet", f"add {csproj_filename} package {package_name}", folder)
1542
1754
 
1543
1755
  @GeneralUtilities.check_arguments
1544
1756
  def create_deb_package(self, toolname: str, binary_folder: str, control_file_content: str,
@@ -1554,24 +1766,30 @@ DNS = {domain}
1554
1766
  # create folder
1555
1767
  GeneralUtilities.ensure_directory_exists(temp_folder)
1556
1768
  control_content_folder_name = "controlcontent"
1557
- packagecontent_control_folder = os.path.join(temp_folder, control_content_folder_name)
1769
+ packagecontent_control_folder = os.path.join(
1770
+ temp_folder, control_content_folder_name)
1558
1771
  GeneralUtilities.ensure_directory_exists(packagecontent_control_folder)
1559
1772
  data_content_folder_name = "datacontent"
1560
- packagecontent_data_folder = os.path.join(temp_folder, data_content_folder_name)
1773
+ packagecontent_data_folder = os.path.join(
1774
+ temp_folder, data_content_folder_name)
1561
1775
  GeneralUtilities.ensure_directory_exists(packagecontent_data_folder)
1562
1776
  entireresult_content_folder_name = "entireresultcontent"
1563
- packagecontent_entireresult_folder = os.path.join(temp_folder, entireresult_content_folder_name)
1564
- GeneralUtilities.ensure_directory_exists(packagecontent_entireresult_folder)
1777
+ packagecontent_entireresult_folder = os.path.join(
1778
+ temp_folder, entireresult_content_folder_name)
1779
+ GeneralUtilities.ensure_directory_exists(
1780
+ packagecontent_entireresult_folder)
1565
1781
 
1566
1782
  # create "debian-binary"-file
1567
- debianbinary_file = os.path.join(packagecontent_entireresult_folder, "debian-binary")
1783
+ debianbinary_file = os.path.join(
1784
+ packagecontent_entireresult_folder, "debian-binary")
1568
1785
  GeneralUtilities.ensure_file_exists(debianbinary_file)
1569
1786
  GeneralUtilities.write_text_to_file(debianbinary_file, "2.0\n")
1570
1787
 
1571
1788
  # create control-content
1572
1789
 
1573
1790
  # conffiles
1574
- conffiles_file = os.path.join(packagecontent_control_folder, "conffiles")
1791
+ conffiles_file = os.path.join(
1792
+ packagecontent_control_folder, "conffiles")
1575
1793
  GeneralUtilities.ensure_file_exists(conffiles_file)
1576
1794
 
1577
1795
  # postinst-script
@@ -1600,53 +1818,58 @@ DNS = {domain}
1600
1818
  # copy binaries
1601
1819
  usr_bin_folder = os.path.join(packagecontent_data_folder, "usr/bin")
1602
1820
  GeneralUtilities.ensure_directory_exists(usr_bin_folder)
1603
- usr_bin_content_folder = os.path.join(usr_bin_folder, tool_content_folder_name)
1604
- GeneralUtilities.copy_content_of_folder(bin_folder, usr_bin_content_folder)
1821
+ usr_bin_content_folder = os.path.join(
1822
+ usr_bin_folder, tool_content_folder_name)
1823
+ GeneralUtilities.copy_content_of_folder(
1824
+ bin_folder, usr_bin_content_folder)
1605
1825
 
1606
1826
  # create debfile
1607
1827
  deb_filename = f"{toolname}.deb"
1608
- self.run_program_argsasarray("tar", ["czf", f"../{entireresult_content_folder_name}/control.tar.gz", "*"], packagecontent_control_folder, verbosity=verbosity)
1609
- self.run_program_argsasarray("tar", ["czf", f"../{entireresult_content_folder_name}/data.tar.gz", "*"], packagecontent_data_folder, verbosity=verbosity)
1610
- self.run_program_argsasarray("ar", ["r", deb_filename, "debian-binary", "control.tar.gz", "data.tar.gz"], packagecontent_entireresult_folder, verbosity=verbosity)
1611
- result_file = os.path.join(packagecontent_entireresult_folder, deb_filename)
1828
+ self.run_program_argsasarray("tar", [
1829
+ "czf", f"../{entireresult_content_folder_name}/control.tar.gz", "*"], packagecontent_control_folder, verbosity=verbosity)
1830
+ self.run_program_argsasarray("tar", [
1831
+ "czf", f"../{entireresult_content_folder_name}/data.tar.gz", "*"], packagecontent_data_folder, verbosity=verbosity)
1832
+ self.run_program_argsasarray("ar", ["r", deb_filename, "debian-binary", "control.tar.gz",
1833
+ "data.tar.gz"], packagecontent_entireresult_folder, verbosity=verbosity)
1834
+ result_file = os.path.join(
1835
+ packagecontent_entireresult_folder, deb_filename)
1612
1836
  shutil.copy(result_file, os.path.join(deb_output_folder, deb_filename))
1613
1837
 
1614
1838
  # cleanup
1615
1839
  GeneralUtilities.ensure_directory_does_not_exist(temp_folder)
1616
1840
 
1617
-
1618
1841
  @GeneralUtilities.check_arguments
1619
1842
  def update_year_in_copyright_tags(self, file: str) -> None:
1620
- current_year=str(datetime.now().year)
1621
- lines=GeneralUtilities.read_lines_from_file(file)
1622
- lines_result=[]
1843
+ current_year = str(datetime.now().year)
1844
+ lines = GeneralUtilities.read_lines_from_file(file)
1845
+ lines_result = []
1623
1846
  for line in lines:
1624
1847
  if match := re.search("(.*<[Cc]opyright>.*)\\d\\d\\d\\d(.*<\\/[Cc]opyright>.*)", line):
1625
1848
  part1 = match.group(1)
1626
1849
  part2 = match.group(2)
1627
- adapted=part1+current_year+part2
1850
+ adapted = part1+current_year+part2
1628
1851
  else:
1629
- adapted=line
1852
+ adapted = line
1630
1853
  lines_result.append(adapted)
1631
- GeneralUtilities.write_lines_to_file(file,lines_result)
1854
+ GeneralUtilities.write_lines_to_file(file, lines_result)
1632
1855
 
1633
1856
  @GeneralUtilities.check_arguments
1634
1857
  def update_year_in_first_line_of_file(self, file: str) -> None:
1635
- current_year=str(datetime.now().year)
1636
- lines=GeneralUtilities.read_lines_from_file(file)
1637
- lines[0]=re.sub("\\d\\d\\d\\d",current_year,lines[0])
1638
- GeneralUtilities.write_lines_to_file(file,lines)
1858
+ current_year = str(datetime.now().year)
1859
+ lines = GeneralUtilities.read_lines_from_file(file)
1860
+ lines[0] = re.sub("\\d\\d\\d\\d", current_year, lines[0])
1861
+ GeneralUtilities.write_lines_to_file(file, lines)
1639
1862
 
1640
1863
  @GeneralUtilities.check_arguments
1641
1864
  def get_external_ip(self, proxy: str) -> str:
1642
- information=self.get_externalnetworkinformation_as_json_string(proxy)
1643
- parsed=json.loads(information)
1865
+ information = self.get_externalnetworkinformation_as_json_string(proxy)
1866
+ parsed = json.loads(information)
1644
1867
  return parsed.ip
1645
1868
 
1646
1869
  @GeneralUtilities.check_arguments
1647
1870
  def get_country_of_external_ip(self, proxy: str) -> str:
1648
- information=self.get_externalnetworkinformation_as_json_string(proxy)
1649
- parsed=json.loads(information)
1871
+ information = self.get_externalnetworkinformation_as_json_string(proxy)
1872
+ parsed = json.loads(information)
1650
1873
  return parsed.country
1651
1874
 
1652
1875
  @GeneralUtilities.check_arguments
@@ -1654,7 +1877,8 @@ DNS = {domain}
1654
1877
  proxies = None
1655
1878
  if GeneralUtilities.string_has_content(proxy):
1656
1879
  proxies = {"http": proxy}
1657
- response = requests.get('https://ipinfo.io', proxies=proxies, timeout=5)
1658
- network_information_as_json_string=GeneralUtilities.bytes_to_string(response.content)
1880
+ response = requests.get('https://ipinfo.io',
1881
+ proxies=proxies, timeout=5)
1882
+ network_information_as_json_string = GeneralUtilities.bytes_to_string(
1883
+ response.content)
1659
1884
  return network_information_as_json_string
1660
-