ScriptCollection 3.5.52__py3-none-any.whl → 3.5.54__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.
@@ -387,3 +387,96 @@ def CreateChangelogEntry() -> int:
387
387
  folder = GeneralUtilities.resolve_relative_path(args.repositoryfolder, os.getcwd())
388
388
  TasksForCommonProjectStructure().create_changelog_entry(folder, args.message, args.commit)
389
389
  return 0
390
+
391
+
392
+ def FileExists() -> int:
393
+ parser = argparse.ArgumentParser(description="This function returns 0 if the given file exists. Otherwise this function returns 2. If an error occurrs the exitcode is 1.")
394
+ parser.add_argument('-p', '--path', required=True)
395
+ args = parser.parse_args()
396
+ if os.path.isfile(args.path):
397
+ return 0
398
+ else:
399
+ return 2
400
+
401
+
402
+ def FolderExists() -> int:
403
+ parser = argparse.ArgumentParser(description="This function returns 0 if the given folder exists. Otherwise this function returns 2. If an error occurrs the exitcode is 1.")
404
+ parser.add_argument('-p', '--path', required=True)
405
+ args = parser.parse_args()
406
+ if os.path.isdir(args.path):
407
+ return 0
408
+ else:
409
+ return 2
410
+
411
+
412
+ def SetContentOfFile() -> int:
413
+ GeneralUtilities.write_exception_to_stderr("This function is not implemented yet.")
414
+ # TODO implement function
415
+ return 1
416
+
417
+
418
+ def PrintFileContent() -> int:
419
+ GeneralUtilities.write_exception_to_stderr("This function is not implemented yet.")
420
+ # TODO implement function
421
+ return 1
422
+
423
+
424
+ def CreateFile() -> int:
425
+ parser = argparse.ArgumentParser(description="This function creates an empty file.")
426
+ parser.add_argument('-p', '--path', required=True)
427
+ parser.add_argument('-e', '--errorwhenexists', action='store_true', required=False, default=False)
428
+ parser.add_argument('-c', '--createnecessaryfolder', action='store_true', required=False, default=False)
429
+ args = parser.parse_args()
430
+ sc = ScriptCollectionCore()
431
+ sc.create_file(args.path, args.errorwhenexists, args.createnecessaryfolder)
432
+ return 0
433
+
434
+
435
+ def CreateFolder() -> int:
436
+ parser = argparse.ArgumentParser(description="This function creates an empty folder.")
437
+ parser.add_argument('-p', '--path', required=True)
438
+ parser.add_argument('-e', '--errorwhenexists', action='store_true', required=False, default=False)
439
+ parser.add_argument('-c', '--createnecessaryfolder', action='store_true', required=False, default=False)
440
+ args = parser.parse_args()
441
+ sc = ScriptCollectionCore()
442
+ sc.create_folder(args.path, args.errorwhenexists, args.createnecessaryfolder)
443
+ return 0
444
+
445
+
446
+ def AppendLineToFile() -> int:
447
+ GeneralUtilities.write_exception_to_stderr("This function is not implemented yet.")
448
+ # TODO implement function
449
+ # TODO add switch to set if adding new line at begin of line should be skipped if the file already ends with a new-line-character
450
+ # TODO add switch to enable/disable appending another new-line-character at the end of the file
451
+ return 1
452
+
453
+
454
+ def RegexReplaceInFile() -> int:
455
+ GeneralUtilities.write_exception_to_stderr("This function is not implemented yet.")
456
+ # TODO implement function
457
+ return 1
458
+
459
+
460
+ def PrintFileSize() -> int:
461
+ GeneralUtilities.write_exception_to_stderr("This function is not implemented yet.")
462
+ # TODO implement function
463
+ return 1
464
+
465
+
466
+ def FileContainsContent() -> int:
467
+ GeneralUtilities.write_exception_to_stderr("This function is not implemented yet.")
468
+ # TODO implement function
469
+ # TODO add switch to set if the input pattern should be treated as regex
470
+ return 1
471
+
472
+
473
+ def RemoveFile() -> int:
474
+ GeneralUtilities.write_exception_to_stderr("This function is not implemented yet.")
475
+ # TODO implement function
476
+ return 1
477
+
478
+
479
+ def RemoveFolder() -> int:
480
+ GeneralUtilities.write_exception_to_stderr("This function is not implemented yet.")
481
+ # TODO implement function
482
+ return 1
@@ -5,6 +5,7 @@ import ctypes
5
5
  import hashlib
6
6
  import re
7
7
  import os
8
+ import subprocess
8
9
  import shutil
9
10
  import urllib
10
11
  import stat
@@ -790,8 +791,13 @@ class GeneralUtilities:
790
791
  @staticmethod
791
792
  @check_arguments
792
793
  def epew_is_available() -> bool:
794
+ return GeneralUtilities.tool_is_available("epew")
795
+
796
+ @staticmethod
797
+ @check_arguments
798
+ def tool_is_available(toolname: str) -> bool:
793
799
  try:
794
- return shutil.which("epew") is not None
800
+ return shutil.which(toolname) is not None
795
801
  except:
796
802
  return False
797
803
 
@@ -873,7 +879,7 @@ class GeneralUtilities:
873
879
  def internet_connection_is_available() -> bool:
874
880
  # TODO add more hosts to check to return true if at least one is available
875
881
  try:
876
- with urllib.request.urlopen("https://google.com") as url_result:
882
+ with urllib.request.urlopen("https://www.google.com") as url_result:
877
883
  return (url_result.code // 100) == 2
878
884
  except:
879
885
  pass
@@ -895,15 +901,14 @@ class GeneralUtilities:
895
901
 
896
902
  @staticmethod
897
903
  @check_arguments
898
- def is_git_repository(folder: str) -> bool:
899
- combined = os.path.join(folder, ".git")
900
- # TODO consider check for bare-repositories
901
- return os.path.isdir(combined) or os.path.isfile(combined)
902
-
903
- @staticmethod
904
- @check_arguments
905
- def assert_is_git_repository(folder: str) -> str:
906
- GeneralUtilities.assert_condition(GeneralUtilities.is_git_repository(folder), f"'{folder}' is not a git-repository.")
904
+ def run_program_simple(program: str, arguments: list[str], cwd: str = None) -> tuple[int, str, str]:
905
+ if cwd is None:
906
+ cwd = os.getcwd()
907
+ cmd = [program]+arguments
908
+ with subprocess.Popen(cmd, cwd=cwd, stderr=subprocess.PIPE, stdout=subprocess.PIPE) as process:
909
+ stdout, stderr = process.communicate()
910
+ exit_code = process.wait()
911
+ return (exit_code, stdout, stderr)
907
912
 
908
913
  @staticmethod
909
914
  @check_arguments
@@ -8,7 +8,7 @@ class ProgramRunnerBase:
8
8
  # Return-values program_runner: Pid
9
9
  @abstractmethod
10
10
  @GeneralUtilities.check_arguments
11
- def run_program_argsasarray_async_helper(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive:bool=False) -> Popen:
11
+ def run_program_argsasarray_async_helper(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> Popen:
12
12
  # Verbosity:
13
13
  # 0=Quiet (No output will be printed.)
14
14
  # 1=Normal (If the exitcode of the executed program is not 0 then the StdErr will be printed.)
@@ -25,23 +25,28 @@ class ProgramRunnerBase:
25
25
  # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
26
26
  @abstractmethod
27
27
  @GeneralUtilities.check_arguments
28
- def run_program_argsasarray(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive:bool=False) -> tuple[int, str, str, int]:
28
+ def run_program_argsasarray(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> tuple[int, str, str, int]:
29
29
  raise NotImplementedError
30
30
 
31
31
  # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
32
32
  @abstractmethod
33
33
  @GeneralUtilities.check_arguments
34
- def run_program(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None, interactive:bool=False) -> tuple[int, str, str, int]:
34
+ def run_program(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> tuple[int, str, str, int]:
35
35
  raise NotImplementedError
36
36
 
37
37
  # Return-values program_runner: Pid
38
38
  @abstractmethod
39
39
  @GeneralUtilities.check_arguments
40
- def run_program_argsasarray_async(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive:bool=False) -> int:
40
+ def run_program_argsasarray_async(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> int:
41
41
  raise NotImplementedError
42
42
 
43
43
  # Return-values program_runner: Pid
44
44
  @abstractmethod
45
45
  @GeneralUtilities.check_arguments
46
- def run_program_async(self, program: str, arguments: str, working_directory: str, custom_argument: object, interactive:bool=False) -> int:
46
+ def run_program_async(self, program: str, arguments: str, working_directory: str, custom_argument: object, interactive: bool = False) -> int:
47
+ raise NotImplementedError
48
+
49
+ @abstractmethod
50
+ @GeneralUtilities.check_arguments
51
+ def will_be_executed_locally(self) -> bool:
47
52
  raise NotImplementedError
@@ -39,7 +39,7 @@ class CustomEpewArgument:
39
39
  class ProgramRunnerEpew(ProgramRunnerBase):
40
40
 
41
41
  @GeneralUtilities.check_arguments
42
- def run_program_argsasarray_async_helper(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive:bool=False) -> Popen:
42
+ def run_program_argsasarray_async_helper(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> Popen:
43
43
  if GeneralUtilities.epew_is_available():
44
44
  custom_argument: CustomEpewArgument = custom_argument
45
45
  args = []
@@ -67,7 +67,7 @@ class ProgramRunnerEpew(ProgramRunnerBase):
67
67
  if custom_argument.addLogOverhead:
68
68
  args.append("-g")
69
69
  args.append("-v "+str(custom_argument.verbosity))
70
- return ProgramRunnerPopen().run_program_argsasarray_async_helper("epew", args, working_directory,custom_argument,interactive)
70
+ return ProgramRunnerPopen().run_program_argsasarray_async_helper("epew", args, working_directory, custom_argument, interactive)
71
71
  else:
72
72
  raise ValueError("Epew is not available.")
73
73
 
@@ -85,21 +85,21 @@ class ProgramRunnerEpew(ProgramRunnerBase):
85
85
  return result
86
86
 
87
87
  @GeneralUtilities.check_arguments
88
- def run_program_argsasarray(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive:bool=False) -> tuple[int, str, str, int]:
89
- process: Popen = self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument,interactive)
88
+ def run_program_argsasarray(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> tuple[int, str, str, int]:
89
+ process: Popen = self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument, interactive)
90
90
  return self.wait(process, custom_argument)
91
91
 
92
92
  @GeneralUtilities.check_arguments
93
- def run_program(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None, interactive:bool=False) -> tuple[int, str, str, int]:
94
- return self.run_program_argsasarray(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument,interactive)
93
+ def run_program(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> tuple[int, str, str, int]:
94
+ return self.run_program_argsasarray(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument, interactive)
95
95
 
96
96
  @GeneralUtilities.check_arguments
97
- def run_program_argsasarray_async(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive:bool=False) -> int:
98
- return self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument,interactive).pid
97
+ def run_program_argsasarray_async(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> int:
98
+ return self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument, interactive).pid
99
99
 
100
100
  @GeneralUtilities.check_arguments
101
- def run_program_async(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None, interactive:bool=False) -> int:
102
- return self.run_program_argsasarray_async(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument,interactive)
101
+ def run_program_async(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> int:
102
+ return self.run_program_argsasarray_async(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument, interactive)
103
103
 
104
104
  @GeneralUtilities.check_arguments
105
105
  def __get_number_from_filecontent(self, filecontent: str) -> int:
@@ -120,3 +120,7 @@ class ProgramRunnerEpew(ProgramRunnerBase):
120
120
  return content
121
121
  else:
122
122
  raise ValueError(f"File '{file}' does not exist")
123
+
124
+ @GeneralUtilities.check_arguments
125
+ def will_be_executed_locally(self) -> bool:
126
+ return True
@@ -51,3 +51,7 @@ class ProgramRunnerPopen(ProgramRunnerBase):
51
51
  @GeneralUtilities.check_arguments
52
52
  def run_program_async(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> int:
53
53
  return self.run_program_argsasarray_async(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument, interactive)
54
+
55
+ @GeneralUtilities.check_arguments
56
+ def will_be_executed_locally(self) -> bool:
57
+ return True
@@ -25,13 +25,13 @@ import yaml
25
25
  import qrcode
26
26
  import pycdlib
27
27
  import send2trash
28
- import PyPDF2
28
+ from pypdf import PdfReader, PdfWriter
29
29
  from .GeneralUtilities import GeneralUtilities
30
30
  from .ProgramRunnerBase import ProgramRunnerBase
31
31
  from .ProgramRunnerPopen import ProgramRunnerPopen
32
32
  from .ProgramRunnerEpew import ProgramRunnerEpew, CustomEpewArgument
33
33
 
34
- version = "3.5.52"
34
+ version = "3.5.54"
35
35
  __version__ = version
36
36
 
37
37
 
@@ -147,7 +147,7 @@ class ScriptCollectionCore:
147
147
 
148
148
  @GeneralUtilities.check_arguments
149
149
  def commit_is_signed_by_key(self, repository_folder: str, revision_identifier: str, key: str) -> bool:
150
- GeneralUtilities.assert_is_git_repository(repository_folder)
150
+ self.assert_is_git_repository(repository_folder)
151
151
  result = self.run_program("git", f"verify-commit {revision_identifier}", repository_folder, throw_exception_if_exitcode_is_not_zero=False)
152
152
  if (result[0] != 0):
153
153
  return False
@@ -161,12 +161,12 @@ class ScriptCollectionCore:
161
161
 
162
162
  @GeneralUtilities.check_arguments
163
163
  def get_parent_commit_ids_of_commit(self, repository_folder: str, commit_id: str) -> str:
164
- GeneralUtilities.assert_is_git_repository(repository_folder)
164
+ self.assert_is_git_repository(repository_folder)
165
165
  return self.run_program("git", f'log --pretty=%P -n 1 "{commit_id}"', repository_folder, throw_exception_if_exitcode_is_not_zero=True)[1].replace("\r", "").replace("\n", "").split(" ")
166
166
 
167
167
  @GeneralUtilities.check_arguments
168
168
  def get_all_authors_and_committers_of_repository(self, repository_folder: str, subfolder: str = None, verbosity: int = 1) -> list[tuple[str, str]]:
169
- GeneralUtilities.assert_is_git_repository(repository_folder)
169
+ self.assert_is_git_repository(repository_folder)
170
170
  space_character = "_"
171
171
  if subfolder is None:
172
172
  subfolder_argument = ""
@@ -186,7 +186,7 @@ class ScriptCollectionCore:
186
186
 
187
187
  @GeneralUtilities.check_arguments
188
188
  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:
189
- GeneralUtilities.assert_is_git_repository(repository_folder)
189
+ self.assert_is_git_repository(repository_folder)
190
190
  since_as_string = self.__datetime_to_string_for_git(since)
191
191
  until_as_string = self.__datetime_to_string_for_git(until)
192
192
  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", ""))
@@ -201,7 +201,7 @@ class ScriptCollectionCore:
201
201
 
202
202
  @GeneralUtilities.check_arguments
203
203
  def git_commit_is_ancestor(self, repository_folder: str, ancestor: str, descendant: str = "HEAD") -> bool:
204
- GeneralUtilities.assert_is_git_repository(repository_folder)
204
+ self.assert_is_git_repository(repository_folder)
205
205
  result = self.run_program_argsasarray("git", ["merge-base", "--is-ancestor", ancestor, descendant], repository_folder, throw_exception_if_exitcode_is_not_zero=False)
206
206
  exit_code = result[0]
207
207
  if exit_code == 0:
@@ -213,7 +213,7 @@ class ScriptCollectionCore:
213
213
 
214
214
  @GeneralUtilities.check_arguments
215
215
  def __git_changes_helper(self, repository_folder: str, arguments_as_array: list[str]) -> bool:
216
- GeneralUtilities.assert_is_git_repository(repository_folder)
216
+ self.assert_is_git_repository(repository_folder)
217
217
  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)
218
218
  for line in lines:
219
219
  if GeneralUtilities.string_has_content(line):
@@ -222,22 +222,22 @@ class ScriptCollectionCore:
222
222
 
223
223
  @GeneralUtilities.check_arguments
224
224
  def git_repository_has_new_untracked_files(self, repository_folder: str):
225
- GeneralUtilities.assert_is_git_repository(repository_folder)
225
+ self.assert_is_git_repository(repository_folder)
226
226
  return self.__git_changes_helper(repository_folder, ["ls-files", "--exclude-standard", "--others"])
227
227
 
228
228
  @GeneralUtilities.check_arguments
229
229
  def git_repository_has_unstaged_changes_of_tracked_files(self, repository_folder: str):
230
- GeneralUtilities.assert_is_git_repository(repository_folder)
230
+ self.assert_is_git_repository(repository_folder)
231
231
  return self.__git_changes_helper(repository_folder, ["--no-pager", "diff"])
232
232
 
233
233
  @GeneralUtilities.check_arguments
234
234
  def git_repository_has_staged_changes(self, repository_folder: str):
235
- GeneralUtilities.assert_is_git_repository(repository_folder)
235
+ self.assert_is_git_repository(repository_folder)
236
236
  return self.__git_changes_helper(repository_folder, ["--no-pager", "diff", "--cached"])
237
237
 
238
238
  @GeneralUtilities.check_arguments
239
239
  def git_repository_has_uncommitted_changes(self, repository_folder: str) -> bool:
240
- GeneralUtilities.assert_is_git_repository(repository_folder)
240
+ self.assert_is_git_repository(repository_folder)
241
241
  if (self.git_repository_has_unstaged_changes(repository_folder)):
242
242
  return True
243
243
  if (self.git_repository_has_staged_changes(repository_folder)):
@@ -246,7 +246,7 @@ class ScriptCollectionCore:
246
246
 
247
247
  @GeneralUtilities.check_arguments
248
248
  def git_repository_has_unstaged_changes(self, repository_folder: str) -> bool:
249
- GeneralUtilities.assert_is_git_repository(repository_folder)
249
+ self.assert_is_git_repository(repository_folder)
250
250
  if (self.git_repository_has_unstaged_changes_of_tracked_files(repository_folder)):
251
251
  return True
252
252
  if (self.git_repository_has_new_untracked_files(repository_folder)):
@@ -255,13 +255,13 @@ class ScriptCollectionCore:
255
255
 
256
256
  @GeneralUtilities.check_arguments
257
257
  def git_get_commit_id(self, repository_folder: str, commit: str = "HEAD") -> str:
258
- GeneralUtilities.assert_is_git_repository(repository_folder)
258
+ self.assert_is_git_repository(repository_folder)
259
259
  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)
260
260
  return result[1].replace('\n', '')
261
261
 
262
262
  @GeneralUtilities.check_arguments
263
263
  def git_get_commit_date(self, repository_folder: str, commit: str = "HEAD") -> datetime:
264
- GeneralUtilities.assert_is_git_repository(repository_folder)
264
+ self.assert_is_git_repository(repository_folder)
265
265
  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)
266
266
  date_as_string = result[1].replace('\n', '')
267
267
  result = datetime.strptime(date_as_string, '%Y-%m-%d %H:%M:%S %z')
@@ -464,7 +464,7 @@ class ScriptCollectionCore:
464
464
  def git_fetch_or_clone_all_in_directory(self, source_directory: str, target_directory: str) -> None:
465
465
  for subfolder in GeneralUtilities.get_direct_folders_of_folder(source_directory):
466
466
  foldername = os.path.basename(subfolder)
467
- if GeneralUtilities.is_git_repository(subfolder):
467
+ if self.is_git_repository(subfolder):
468
468
  source_repository = subfolder
469
469
  target_repository = os.path.join(target_directory, foldername)
470
470
  if os.path.isdir(target_directory):
@@ -534,20 +534,20 @@ class ScriptCollectionCore:
534
534
 
535
535
  @GeneralUtilities.check_arguments
536
536
  def get_current_git_branch_has_tag(self, repository_folder: str) -> bool:
537
- GeneralUtilities.assert_is_git_repository(repository_folder)
537
+ self.assert_is_git_repository(repository_folder)
538
538
  result = self.run_program_argsasarray("git", ["describe", "--tags", "--abbrev=0"], repository_folder, verbosity=0, throw_exception_if_exitcode_is_not_zero=False)
539
539
  return result[0] == 0
540
540
 
541
541
  @GeneralUtilities.check_arguments
542
542
  def get_latest_git_tag(self, repository_folder: str) -> str:
543
- GeneralUtilities.assert_is_git_repository(repository_folder)
543
+ self.assert_is_git_repository(repository_folder)
544
544
  result = self.run_program_argsasarray("git", ["describe", "--tags", "--abbrev=0"], repository_folder, verbosity=0)
545
545
  result = result[1].replace("\r", "").replace("\n", "")
546
546
  return result
547
547
 
548
548
  @GeneralUtilities.check_arguments
549
549
  def get_staged_or_committed_git_ignored_files(self, repository_folder: str) -> list[str]:
550
- GeneralUtilities.assert_is_git_repository(repository_folder)
550
+ self.assert_is_git_repository(repository_folder)
551
551
  temp_result = self.run_program_argsasarray("git", ["ls-files", "-i", "-c", "--exclude-standard"], repository_folder, verbosity=0)
552
552
  temp_result = temp_result[1].replace("\r", "")
553
553
  result = [line for line in temp_result.split("\n") if len(line) > 0]
@@ -555,7 +555,7 @@ class ScriptCollectionCore:
555
555
 
556
556
  @GeneralUtilities.check_arguments
557
557
  def git_repository_has_commits(self, repository_folder: str) -> bool:
558
- GeneralUtilities.assert_is_git_repository(repository_folder)
558
+ self.assert_is_git_repository(repository_folder)
559
559
  return self.run_program_argsasarray("git", ["rev-parse", "--verify", "HEAD"], repository_folder, throw_exception_if_exitcode_is_not_zero=False)[0] == 0
560
560
 
561
561
  @GeneralUtilities.check_arguments
@@ -609,6 +609,44 @@ class ScriptCollectionCore:
609
609
  for renamed_item, original_name in renamed_items.items():
610
610
  os.rename(renamed_item, original_name)
611
611
 
612
+ @GeneralUtilities.check_arguments
613
+ def is_file(self, path: str) -> bool:
614
+ if self.program_runner.will_be_executed_locally():
615
+ return os.path.isfile(path) # much more performant than always running an external program
616
+ else:
617
+ exit_code, _, stderr = self.run_program("scfileexists", ["--path", path], throw_exception_if_exitcode_is_not_zero=False) # works platform-indepent
618
+ if exit_code == 0:
619
+ return True
620
+ elif exit_code == 1:
621
+ raise ValueError(f"Not calculatable whether file '{path}' exists. StdErr: '{stderr}'")
622
+ elif exit_code == 2:
623
+ return False
624
+ raise ValueError(f"Fatal error occurrs while checking whether file '{path}' exists. StdErr: '{stderr}'")
625
+
626
+ @GeneralUtilities.check_arguments
627
+ def is_folder(self, path: str) -> bool:
628
+ if self.program_runner.will_be_executed_locally(): # much more performant than always running an external program
629
+ return os.path.isdir(path)
630
+ else:
631
+ exit_code, _, stderr = self.run_program("scfolderexists", ["--path", path], throw_exception_if_exitcode_is_not_zero=False) # works platform-indepent
632
+ if exit_code == 0:
633
+ return True
634
+ elif exit_code == 1:
635
+ raise ValueError(f"Not calculatable whether folder '{path}' exists. StdErr: '{stderr}'")
636
+ elif exit_code == 2:
637
+ return False
638
+ raise ValueError(f"Fatal error occurrs while checking whether folder '{path}' exists. StdErr: '{stderr}'")
639
+
640
+ @GeneralUtilities.check_arguments
641
+ def is_git_repository(self, folder: str) -> bool:
642
+ combined = f"{folder}/.git"
643
+ # TODO consider check for bare-repositories
644
+ return self.is_file(combined) or self.is_folder(combined)
645
+
646
+ @GeneralUtilities.check_arguments
647
+ def assert_is_git_repository(self, folder: str) -> str:
648
+ GeneralUtilities.assert_condition(self.is_git_repository(folder), f"'{folder}' is not a git-repository.")
649
+
612
650
  @GeneralUtilities.check_arguments
613
651
  def __sort_fmd(self, line: str):
614
652
  splitted: list = line.split(";")
@@ -715,8 +753,8 @@ class ScriptCollectionCore:
715
753
 
716
754
  @GeneralUtilities.check_arguments
717
755
  def extract_pdf_pages(self, file: str, from_page: int, to_page: int, outputfile: str) -> None:
718
- pdf_reader = PyPDF2.PdfReader(file)
719
- pdf_writer = PyPDF2.PdfWriter()
756
+ pdf_reader: PdfReader = PdfReader(file)
757
+ pdf_writer: PdfWriter = PdfWriter()
720
758
  start = from_page
721
759
  end = to_page
722
760
  while start <= end:
@@ -728,11 +766,13 @@ class ScriptCollectionCore:
728
766
  @GeneralUtilities.check_arguments
729
767
  def merge_pdf_files(self, files: list[str], outputfile: str) -> None:
730
768
  # TODO add wildcard-option
731
- pdfFileMerger = PyPDF2.PdfFileMerger()
769
+ pdfFileMerger: PdfWriter = PdfWriter()
732
770
  for file in files:
733
- pdfFileMerger.append(file.strip())
734
- pdfFileMerger.write(outputfile)
735
- pdfFileMerger.close()
771
+ with open(file, "rb") as f:
772
+ pdfFileMerger.append(f)
773
+ with open(outputfile, "wb") as output:
774
+ pdfFileMerger.write(output)
775
+ pdfFileMerger.close()
736
776
 
737
777
  @GeneralUtilities.check_arguments
738
778
  def pdf_to_image(self, file: str, outputfilename_without_extension: str) -> None:
@@ -1120,7 +1160,7 @@ class ScriptCollectionCore:
1120
1160
  return tor_version
1121
1161
 
1122
1162
  def run_testcases_for_python_project(self, repository_folder: str):
1123
- GeneralUtilities.assert_is_git_repository(repository_folder)
1163
+ self.assert_is_git_repository(repository_folder)
1124
1164
  self.run_program("coverage", "run -m pytest", repository_folder)
1125
1165
  self.run_program("coverage", "xml", repository_folder)
1126
1166
  GeneralUtilities.ensure_directory_exists(os.path.join(repository_folder, "Other/TestCoverage"))
@@ -1534,7 +1574,7 @@ class ScriptCollectionCore:
1534
1574
 
1535
1575
  @GeneralUtilities.check_arguments
1536
1576
  def get_semver_version_from_gitversion(self, repository_folder: str) -> str:
1537
- GeneralUtilities.assert_is_git_repository(repository_folder)
1577
+ self.assert_is_git_repository(repository_folder)
1538
1578
  if (self.git_repository_has_commits(repository_folder)):
1539
1579
  result = self.get_version_from_gitversion(repository_folder, "MajorMinorPatch")
1540
1580
  if self.git_repository_has_uncommitted_changes(repository_folder):
@@ -1569,7 +1609,7 @@ class ScriptCollectionCore:
1569
1609
  if password is None:
1570
1610
  password = GeneralUtilities.generate_password()
1571
1611
  GeneralUtilities.ensure_directory_exists(folder)
1572
- 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)
1612
+ self.run_program_argsasarray("openssl", ['req', '-new', '-newkey', 'ec', '-pkeyopt', 'ec_paramgen_curve:prime256v1', '-days', str(days_until_expire), '-nodes', '-x509', '-subj', f'/C={subj_c}/ST={subj_st}/L={subj_l}/O={subj_o}/CN={name}/OU={subj_ou}', '-passout', f'pass:{password}', '-keyout', f'{name}.key', '-out', f'{name}.crt'], folder)
1573
1613
 
1574
1614
  @GeneralUtilities.check_arguments
1575
1615
  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:
@@ -1578,9 +1618,9 @@ class ScriptCollectionCore:
1578
1618
  if password is None:
1579
1619
  password = GeneralUtilities.generate_password()
1580
1620
  rsa_key_length = 4096
1581
- self.run_program("openssl", f'genrsa -out {filename}.key {rsa_key_length}', folder)
1582
- 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)
1583
- self.run_program("openssl", f'pkcs12 -export -out {filename}.selfsigned.pfx -password pass:{password} -inkey {filename}.key -in {filename}.unsigned.crt', folder)
1621
+ self.run_program_argsasarray("openssl", ['genrsa', '-out', f'{filename}.key', f'{rsa_key_length}'], folder)
1622
+ self.run_program_argsasarray("openssl", ['req', '-new', '-subj', f'/C={subj_c}/ST={subj_st}/L={subj_l}/O={subj_o}/CN={domain}/OU={subj_ou}', '-x509', '-key', f'{filename}.key', '-out', f'{filename}.unsigned.crt', '-days', f'{days_until_expire}'], folder)
1623
+ self.run_program_argsasarray("openssl", ['pkcs12', '-export', '-out', f'{filename}.selfsigned.pfx', '-password', f'pass:{password}', '-inkey', f'{filename}.key', '-in', f'{filename}.unsigned.crt'], folder)
1584
1624
  GeneralUtilities.write_text_to_file(os.path.join(folder, f"{filename}.password"), password)
1585
1625
  GeneralUtilities.write_text_to_file(os.path.join(folder, f"{filename}.san.conf"), f"""[ req ]
1586
1626
  default_bits = {rsa_key_length}
@@ -1607,7 +1647,7 @@ DNS = {domain}
1607
1647
 
1608
1648
  @GeneralUtilities.check_arguments
1609
1649
  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:
1610
- 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)
1650
+ self.run_program_argsasarray("openssl", ['req', '-new', '-subj', f'/C={subj_c}/ST={subj_st}/L={subj_l}/O={subj_o}/CN={domain}/OU={subj_ou}', '-key', f'{filename}.key', f'-out', f'{filename}.csr', f'-config', f'{filename}.san.conf'], folder)
1611
1651
 
1612
1652
  @GeneralUtilities.check_arguments
1613
1653
  def sign_certificate(self, folder: str, ca_folder: str, ca_name: str, domain: str, filename: str, days_until_expire: int = None) -> None:
@@ -1616,8 +1656,8 @@ DNS = {domain}
1616
1656
  ca = os.path.join(ca_folder, ca_name)
1617
1657
  password_file = os.path.join(folder, f"{filename}.password")
1618
1658
  password = GeneralUtilities.read_text_from_file(password_file)
1619
- 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)
1620
- self.run_program("openssl", f'pkcs12 -export -out {filename}.pfx -inkey {filename}.key -in {filename}.crt -password pass:{password}', folder)
1659
+ self.run_program_argsasarray("openssl", ['x509', '-req', '-in', f'{filename}.csr', '-CA', f'{ca}.crt', '-CAkey', f'{ca}.key', '-CAcreateserial', '-CAserial', f'{ca}.srl', '-out', f'{filename}.crt', '-days', str(days_until_expire), '-sha256', '-extensions', 'v3_req', '-extfile', f'{filename}.san.conf'], folder)
1660
+ self.run_program_argsasarray("openssl", ['pkcs12', '-export', '-out', f'{filename}.pfx', f'-inkey', f'{filename}.key', '-in', f'{filename}.crt', '-password', f'pass:{password}'], folder)
1621
1661
 
1622
1662
  @GeneralUtilities.check_arguments
1623
1663
  def update_dependencies_of_python_in_requirementstxt_file(self, file: str, verbosity: int):
@@ -1984,3 +2024,43 @@ TXDX
1984
2024
  @GeneralUtilities.check_arguments
1985
2025
  def create_local_docker_network(self, network_name: str) -> None:
1986
2026
  self.run_program("docker", f"network create {network_name}")
2027
+
2028
+ @GeneralUtilities.check_arguments
2029
+ def create_file(self, path: str, error_if_already_exists: bool, create_necessary_folder: bool) -> None:
2030
+ if not os.path.isabs(path):
2031
+ path = os.path.join(os.getcwd(), path)
2032
+
2033
+ if os.path.isfile(path) and error_if_already_exists:
2034
+ raise ValueError(f"File '{path}' already exists.")
2035
+
2036
+ # TODO maybe it should be checked if there is a folder with the same path which already exists.
2037
+
2038
+ folder = os.path.dirname(path)
2039
+
2040
+ if not os.path.isdir(folder):
2041
+ if create_necessary_folder:
2042
+ GeneralUtilities.ensure_directory_exists(folder) # TODO check if this also create nested folders if required
2043
+ else:
2044
+ raise ValueError(f"Folder '{folder}' does not exist.")
2045
+
2046
+ GeneralUtilities.ensure_file_exists(path)
2047
+
2048
+ @GeneralUtilities.check_arguments
2049
+ def create_folder(self, path: str, error_if_already_exists: bool, create_necessary_folder: bool) -> None:
2050
+ if not os.path.isabs(path):
2051
+ path = os.path.join(os.getcwd(), path)
2052
+
2053
+ if os.path.isdir(path) and error_if_already_exists:
2054
+ raise ValueError(f"Folder '{path}' already exists.")
2055
+
2056
+ # TODO maybe it should be checked if there is a file with the same path which already exists.
2057
+
2058
+ folder = os.path.dirname(path)
2059
+
2060
+ if not os.path.isdir(folder):
2061
+ if create_necessary_folder:
2062
+ GeneralUtilities.ensure_directory_exists(folder) # TODO check if this also create nested folders if required
2063
+ else:
2064
+ raise ValueError(f"Folder '{folder}' does not exist.")
2065
+
2066
+ GeneralUtilities.ensure_directory_exists(path)