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