ScriptCollection 3.5.12__py3-none-any.whl → 3.5.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ScriptCollection/GeneralUtilities.py +6 -2
- ScriptCollection/ProgramRunnerPopen.py +10 -10
- ScriptCollection/ScriptCollectionCore.py +138 -223
- {ScriptCollection-3.5.12.dist-info → ScriptCollection-3.5.14.dist-info}/METADATA +1 -1
- {ScriptCollection-3.5.12.dist-info → ScriptCollection-3.5.14.dist-info}/RECORD +8 -8
- {ScriptCollection-3.5.12.dist-info → ScriptCollection-3.5.14.dist-info}/WHEEL +1 -1
- {ScriptCollection-3.5.12.dist-info → ScriptCollection-3.5.14.dist-info}/entry_points.txt +0 -0
- {ScriptCollection-3.5.12.dist-info → ScriptCollection-3.5.14.dist-info}/top_level.txt +0 -0
|
@@ -67,7 +67,7 @@ class GeneralUtilities:
|
|
|
67
67
|
@functools.wraps(func)
|
|
68
68
|
def new_func(*args, **kwargs):
|
|
69
69
|
warnings.simplefilter('always', DeprecationWarning)
|
|
70
|
-
warnings.warn(f"Call to deprecated function {func.__name__}",
|
|
70
|
+
warnings.warn(f"Call to deprecated function {func.__name__}", category=DeprecationWarning, stacklevel=2)
|
|
71
71
|
warnings.simplefilter('default', DeprecationWarning)
|
|
72
72
|
return func(*args, **kwargs)
|
|
73
73
|
return new_func
|
|
@@ -574,12 +574,14 @@ class GeneralUtilities:
|
|
|
574
574
|
@check_arguments
|
|
575
575
|
def get_direct_files_of_folder(folder: str) -> list[str]:
|
|
576
576
|
result = [os.path.join(folder, f) for f in listdir(folder) if isfile(join(folder, f))]
|
|
577
|
+
result = sorted(result, key=str.casefold)
|
|
577
578
|
return result
|
|
578
579
|
|
|
579
580
|
@staticmethod
|
|
580
581
|
@check_arguments
|
|
581
582
|
def get_direct_folders_of_folder(folder: str) -> list[str]:
|
|
582
583
|
result = [os.path.join(folder, f) for f in listdir(folder) if isdir(join(folder, f))]
|
|
584
|
+
result = sorted(result, key=str.casefold)
|
|
583
585
|
return result
|
|
584
586
|
|
|
585
587
|
@staticmethod
|
|
@@ -589,6 +591,7 @@ class GeneralUtilities:
|
|
|
589
591
|
result.extend(GeneralUtilities.get_direct_files_of_folder(folder))
|
|
590
592
|
for subfolder in GeneralUtilities.get_direct_folders_of_folder(folder):
|
|
591
593
|
result.extend(GeneralUtilities.get_all_files_of_folder(subfolder))
|
|
594
|
+
result = sorted(result, key=str.casefold)
|
|
592
595
|
return result
|
|
593
596
|
|
|
594
597
|
@staticmethod
|
|
@@ -599,12 +602,13 @@ class GeneralUtilities:
|
|
|
599
602
|
result.extend(subfolders)
|
|
600
603
|
for subfolder in subfolders:
|
|
601
604
|
result.extend(GeneralUtilities.get_all_folders_of_folder(subfolder))
|
|
605
|
+
result = sorted(result, key=str.casefold)
|
|
602
606
|
return result
|
|
603
607
|
|
|
604
608
|
@staticmethod
|
|
605
609
|
@check_arguments
|
|
606
610
|
def get_all_objects_of_folder(folder: str) -> list[str]:
|
|
607
|
-
return GeneralUtilities.get_all_files_of_folder(folder) + GeneralUtilities.get_all_folders_of_folder(folder)
|
|
611
|
+
return sorted(GeneralUtilities.get_all_files_of_folder(folder) + GeneralUtilities.get_all_folders_of_folder(folder), key=str.casefold)
|
|
608
612
|
|
|
609
613
|
@staticmethod
|
|
610
614
|
@check_arguments
|
|
@@ -7,7 +7,7 @@ from .ProgramRunnerBase import ProgramRunnerBase
|
|
|
7
7
|
class ProgramRunnerPopen(ProgramRunnerBase):
|
|
8
8
|
|
|
9
9
|
@GeneralUtilities.check_arguments
|
|
10
|
-
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:
|
|
10
|
+
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
11
|
arguments_for_process = [program]
|
|
12
12
|
arguments_for_process.extend(arguments_as_array)
|
|
13
13
|
# "shell=True" is not allowed because it is not recommended and also something like
|
|
@@ -15,9 +15,9 @@ class ProgramRunnerPopen(ProgramRunnerBase):
|
|
|
15
15
|
# would not be possible anymore because the ampersand will be treated as shell-command.
|
|
16
16
|
try:
|
|
17
17
|
if interactive:
|
|
18
|
-
result = Popen(arguments_for_process, cwd=working_directory
|
|
18
|
+
result = Popen(arguments_for_process, cwd=working_directory, stdout=PIPE, stderr=PIPE, shell=False, text=True, stdin=sys.stdin) # pylint: disable=consider-using-with
|
|
19
19
|
else:
|
|
20
|
-
result = Popen(arguments_for_process, cwd=working_directory, stdout=PIPE, stderr=PIPE, shell=False) # pylint: disable=consider-using-with
|
|
20
|
+
result = Popen(arguments_for_process, cwd=working_directory, stdout=PIPE, stderr=PIPE, shell=False, text=True) # pylint: disable=consider-using-with
|
|
21
21
|
except FileNotFoundError as fileNotFoundError:
|
|
22
22
|
raise FileNotFoundError(f"Starting '{program}' in '{working_directory}' resulted in a FileNotFoundError: '{fileNotFoundError.filename}'")
|
|
23
23
|
return result
|
|
@@ -34,18 +34,18 @@ class ProgramRunnerPopen(ProgramRunnerBase):
|
|
|
34
34
|
return result
|
|
35
35
|
|
|
36
36
|
@GeneralUtilities.check_arguments
|
|
37
|
-
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]:
|
|
38
|
-
process: Popen = self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument,interactive)
|
|
37
|
+
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]:
|
|
38
|
+
process: Popen = self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument, interactive)
|
|
39
39
|
return self.wait(process, custom_argument)
|
|
40
40
|
|
|
41
41
|
@GeneralUtilities.check_arguments
|
|
42
|
-
def run_program(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None, interactive:bool=False) -> tuple[int, str, str, int]:
|
|
42
|
+
def run_program(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> tuple[int, str, str, int]:
|
|
43
43
|
return self.run_program_argsasarray(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument)
|
|
44
44
|
|
|
45
45
|
@GeneralUtilities.check_arguments
|
|
46
|
-
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:
|
|
47
|
-
return self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument,interactive).pid
|
|
46
|
+
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:
|
|
47
|
+
return self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument, interactive).pid
|
|
48
48
|
|
|
49
49
|
@GeneralUtilities.check_arguments
|
|
50
|
-
def run_program_async(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None, interactive:bool=False) -> int:
|
|
51
|
-
return self.run_program_argsasarray_async(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument,interactive)
|
|
50
|
+
def run_program_async(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None, interactive: bool = False) -> int:
|
|
51
|
+
return self.run_program_argsasarray_async(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument, interactive)
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import time
|
|
2
1
|
from datetime import timedelta, datetime
|
|
3
2
|
import json
|
|
4
3
|
import binascii
|
|
5
4
|
import filecmp
|
|
5
|
+
import time
|
|
6
6
|
import hashlib
|
|
7
|
-
from io import
|
|
7
|
+
from io import BytesIO
|
|
8
8
|
import itertools
|
|
9
9
|
import math
|
|
10
10
|
import os
|
|
11
|
+
from queue import Queue, Empty
|
|
12
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
11
13
|
from pathlib import Path
|
|
12
|
-
from random import randrange
|
|
13
14
|
from subprocess import Popen
|
|
14
15
|
import re
|
|
15
16
|
import shutil
|
|
16
|
-
import traceback
|
|
17
17
|
import uuid
|
|
18
18
|
import tempfile
|
|
19
19
|
import io
|
|
@@ -29,7 +29,7 @@ from .ProgramRunnerBase import ProgramRunnerBase
|
|
|
29
29
|
from .ProgramRunnerPopen import ProgramRunnerPopen
|
|
30
30
|
from .ProgramRunnerEpew import ProgramRunnerEpew, CustomEpewArgument
|
|
31
31
|
|
|
32
|
-
version = "3.5.
|
|
32
|
+
version = "3.5.14"
|
|
33
33
|
__version__ = version
|
|
34
34
|
|
|
35
35
|
|
|
@@ -59,8 +59,7 @@ class ScriptCollectionCore:
|
|
|
59
59
|
errorsonly_argument = ""
|
|
60
60
|
else:
|
|
61
61
|
errorsonly_argument = " --errors-only"
|
|
62
|
-
(exit_code, stdout, stderr, _) = self.run_program("pylint", filename +
|
|
63
|
-
errorsonly_argument, working_directory, throw_exception_if_exitcode_is_not_zero=False)
|
|
62
|
+
(exit_code, stdout, stderr, _) = self.run_program("pylint", filename + errorsonly_argument, working_directory, throw_exception_if_exitcode_is_not_zero=False)
|
|
64
63
|
if (exit_code != 0):
|
|
65
64
|
errors.append(f"Linting-issues of {file}:")
|
|
66
65
|
errors.append(f"Pylint-exitcode: {exit_code}")
|
|
@@ -74,18 +73,15 @@ class ScriptCollectionCore:
|
|
|
74
73
|
|
|
75
74
|
@GeneralUtilities.check_arguments
|
|
76
75
|
def replace_version_in_dockerfile_file(self, dockerfile: str, new_version_value: str) -> None:
|
|
77
|
-
GeneralUtilities.write_text_to_file(dockerfile, re.sub(
|
|
78
|
-
"ARG Version=\"\\d+\\.\\d+\\.\\d+\"", f"ARG Version=\"{new_version_value}\"", GeneralUtilities.read_text_from_file(dockerfile)))
|
|
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)))
|
|
79
77
|
|
|
80
78
|
@GeneralUtilities.check_arguments
|
|
81
79
|
def replace_version_in_python_file(self, file: str, new_version_value: str):
|
|
82
|
-
GeneralUtilities.write_text_to_file(file, re.sub(
|
|
83
|
-
"version = \"\\d+\\.\\d+\\.\\d+\"", f"version = \"{new_version_value}\"", GeneralUtilities.read_text_from_file(file)))
|
|
80
|
+
GeneralUtilities.write_text_to_file(file, re.sub("version = \"\\d+\\.\\d+\\.\\d+\"", f"version = \"{new_version_value}\"", GeneralUtilities.read_text_from_file(file)))
|
|
84
81
|
|
|
85
82
|
@GeneralUtilities.check_arguments
|
|
86
83
|
def replace_version_in_ini_file(self, file: str, new_version_value: str):
|
|
87
|
-
GeneralUtilities.write_text_to_file(file, re.sub(
|
|
88
|
-
"version = \\d+\\.\\d+\\.\\d+", f"version = {new_version_value}", GeneralUtilities.read_text_from_file(file)))
|
|
84
|
+
GeneralUtilities.write_text_to_file(file, re.sub("version = \\d+\\.\\d+\\.\\d+", f"version = {new_version_value}", GeneralUtilities.read_text_from_file(file)))
|
|
89
85
|
|
|
90
86
|
@GeneralUtilities.check_arguments
|
|
91
87
|
def replace_version_in_nuspec_file(self, nuspec_file: str, new_version: str) -> None:
|
|
@@ -96,8 +92,7 @@ class ScriptCollectionCore:
|
|
|
96
92
|
if pattern.match(new_version):
|
|
97
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)))
|
|
98
94
|
else:
|
|
99
|
-
raise ValueError(
|
|
100
|
-
f"Version '{new_version}' does not match version-regex '{versiononlyregex}'")
|
|
95
|
+
raise ValueError(f"Version '{new_version}' does not match version-regex '{versiononlyregex}'")
|
|
101
96
|
|
|
102
97
|
@GeneralUtilities.check_arguments
|
|
103
98
|
def replace_version_in_csproj_file(self, csproj_file: str, current_version: str):
|
|
@@ -106,25 +101,20 @@ class ScriptCollectionCore:
|
|
|
106
101
|
pattern = re.compile(versiononlyregex)
|
|
107
102
|
if pattern.match(current_version):
|
|
108
103
|
for tag in ["Version", "AssemblyVersion", "FileVersion"]:
|
|
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)))
|
|
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)))
|
|
111
105
|
else:
|
|
112
|
-
raise ValueError(
|
|
113
|
-
f"Version '{current_version}' does not match version-regex '{versiononlyregex}'")
|
|
106
|
+
raise ValueError(f"Version '{current_version}' does not match version-regex '{versiononlyregex}'")
|
|
114
107
|
|
|
115
108
|
@GeneralUtilities.check_arguments
|
|
116
109
|
def push_nuget_build_artifact(self, nupkg_file: str, registry_address: str, api_key: str, verbosity: int = 1):
|
|
117
110
|
nupkg_file_name = os.path.basename(nupkg_file)
|
|
118
111
|
nupkg_file_folder = os.path.dirname(nupkg_file)
|
|
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)
|
|
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)
|
|
121
113
|
|
|
122
114
|
@GeneralUtilities.check_arguments
|
|
123
115
|
def dotnet_build(self, repository_folder: str, projectname: str, configuration: str):
|
|
124
|
-
self.run_program(
|
|
125
|
-
|
|
126
|
-
self.run_program(
|
|
127
|
-
"dotnet", f"build {projectname}/{projectname}.csproj -c {configuration}", repository_folder)
|
|
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)
|
|
128
118
|
|
|
129
119
|
@GeneralUtilities.check_arguments
|
|
130
120
|
def find_file_by_extension(self, folder: str, extension: str):
|
|
@@ -162,8 +152,7 @@ class ScriptCollectionCore:
|
|
|
162
152
|
subfolder_argument = ""
|
|
163
153
|
else:
|
|
164
154
|
subfolder_argument = f" -- {subfolder}"
|
|
165
|
-
log_result = self.run_program(
|
|
166
|
-
"git", f'log --pretty=%aN{space_character}%aE%n%cN{space_character}%cE HEAD{subfolder_argument}', repository_folder, verbosity=0)
|
|
155
|
+
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)
|
|
167
156
|
plain_content: list[str] = list(
|
|
168
157
|
set([line for line in log_result[1].split("\n") if len(line) > 0]))
|
|
169
158
|
result: list[tuple[str, str]] = []
|
|
@@ -179,8 +168,7 @@ class ScriptCollectionCore:
|
|
|
179
168
|
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:
|
|
180
169
|
since_as_string = self.__datetime_to_string_for_git(since)
|
|
181
170
|
until_as_string = self.__datetime_to_string_for_git(until)
|
|
182
|
-
result = filter(lambda line: not GeneralUtilities.string_is_none_or_whitespace(line), self.run_program(
|
|
183
|
-
"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", ""))
|
|
171
|
+
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", ""))
|
|
184
172
|
if ignore_commits_which_are_not_in_history_of_head:
|
|
185
173
|
result = [commit_id for commit_id in result if self.git_commit_is_ancestor(
|
|
186
174
|
repository_folder, commit_id)]
|
|
@@ -192,8 +180,7 @@ class ScriptCollectionCore:
|
|
|
192
180
|
|
|
193
181
|
@GeneralUtilities.check_arguments
|
|
194
182
|
def git_commit_is_ancestor(self, repository_folder: str, ancestor: str, descendant: str = "HEAD") -> bool:
|
|
195
|
-
exit_code = self.run_program_argsasarray(
|
|
196
|
-
"git", ["merge-base", "--is-ancestor", ancestor, descendant], repository_folder, throw_exception_if_exitcode_is_not_zero=False)[0]
|
|
183
|
+
exit_code = self.run_program_argsasarray("git", ["merge-base", "--is-ancestor", ancestor, descendant], repository_folder, throw_exception_if_exitcode_is_not_zero=False)[0]
|
|
197
184
|
if exit_code == 0:
|
|
198
185
|
return True
|
|
199
186
|
elif exit_code == 1:
|
|
@@ -203,8 +190,7 @@ class ScriptCollectionCore:
|
|
|
203
190
|
|
|
204
191
|
@GeneralUtilities.check_arguments
|
|
205
192
|
def __git_changes_helper(self, repository_folder: str, arguments_as_array: list[str]) -> bool:
|
|
206
|
-
lines = GeneralUtilities.string_to_lines(self.run_program_argsasarray(
|
|
207
|
-
"git", arguments_as_array, repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)[1], False)
|
|
193
|
+
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)
|
|
208
194
|
for line in lines:
|
|
209
195
|
if GeneralUtilities.string_has_content(line):
|
|
210
196
|
return True
|
|
@@ -245,8 +231,7 @@ class ScriptCollectionCore:
|
|
|
245
231
|
|
|
246
232
|
@GeneralUtilities.check_arguments
|
|
247
233
|
def git_get_commit_date(self, repository_folder: str, commit: str = "HEAD") -> datetime:
|
|
248
|
-
result: tuple[int, str, str, int] = self.run_program_argsasarray(
|
|
249
|
-
"git", ["show", "-s", "--format=%ci", commit], repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
|
234
|
+
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)
|
|
250
235
|
date_as_string = result[1].replace('\n', '')
|
|
251
236
|
result = datetime.strptime(date_as_string, '%Y-%m-%d %H:%M:%S %z')
|
|
252
237
|
return result
|
|
@@ -359,8 +344,7 @@ class ScriptCollectionCore:
|
|
|
359
344
|
self.run_program_argsasarray("git", ['checkout', '.'], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
|
360
345
|
|
|
361
346
|
@GeneralUtilities.check_arguments
|
|
362
|
-
def git_commit(self, directory: str, message: str, author_name: str = None, author_email: str = None, stage_all_changes: bool = True,
|
|
363
|
-
no_changes_behavior: int = 0) -> str:
|
|
347
|
+
def git_commit(self, directory: str, message: str, author_name: str = None, author_email: str = None, stage_all_changes: bool = True, no_changes_behavior: int = 0) -> str:
|
|
364
348
|
# no_changes_behavior=0 => No commit
|
|
365
349
|
# no_changes_behavior=1 => Commit anyway
|
|
366
350
|
# no_changes_behavior=2 => Exception
|
|
@@ -410,7 +394,7 @@ class ScriptCollectionCore:
|
|
|
410
394
|
@GeneralUtilities.check_arguments
|
|
411
395
|
def git_checkout(self, directory: str, branch: str) -> None:
|
|
412
396
|
self.run_program_argsasarray("git", ["checkout", branch], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
|
413
|
-
self.run_program_argsasarray("git", ["submodule", "update", "--recursive"],
|
|
397
|
+
self.run_program_argsasarray("git", ["submodule", "update", "--recursive"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
|
414
398
|
|
|
415
399
|
@GeneralUtilities.check_arguments
|
|
416
400
|
def git_merge_abort(self, directory: str) -> None:
|
|
@@ -450,7 +434,7 @@ class ScriptCollectionCore:
|
|
|
450
434
|
self.git_fetch(target_directory)
|
|
451
435
|
else:
|
|
452
436
|
# clone
|
|
453
|
-
self.git_clone(target_repository, source_repository,
|
|
437
|
+
self.git_clone(target_repository, source_repository, include_submodules=True, mirror=True)
|
|
454
438
|
|
|
455
439
|
def get_git_submodules(self, folder: str) -> list[str]:
|
|
456
440
|
e = self.run_program("git", "submodule status", folder)
|
|
@@ -472,8 +456,7 @@ class ScriptCollectionCore:
|
|
|
472
456
|
return True
|
|
473
457
|
if (exit_code == 1):
|
|
474
458
|
return False
|
|
475
|
-
raise ValueError(
|
|
476
|
-
f"Unable to calculate whether '{file_in_repository}' in repository '{repositorybasefolder}' is ignored due to git-exitcode {exit_code}.")
|
|
459
|
+
raise ValueError(f"Unable to calculate whether '{file_in_repository}' in repository '{repositorybasefolder}' is ignored due to git-exitcode {exit_code}.")
|
|
477
460
|
|
|
478
461
|
@GeneralUtilities.check_arguments
|
|
479
462
|
def git_discard_all_changes(self, repository: str) -> None:
|
|
@@ -562,9 +545,11 @@ class ScriptCollectionCore:
|
|
|
562
545
|
with open(target_file, "w", encoding=encoding) as file_object:
|
|
563
546
|
file_object.write("\n".join(lines))
|
|
564
547
|
|
|
548
|
+
@GeneralUtilities.check_arguments
|
|
565
549
|
def escape_git_repositories_in_folder(self, folder: str) -> dict[str, str]:
|
|
566
550
|
return self.__escape_git_repositories_in_folder_internal(folder, dict[str, str]())
|
|
567
551
|
|
|
552
|
+
@GeneralUtilities.check_arguments
|
|
568
553
|
def __escape_git_repositories_in_folder_internal(self, folder: str, renamed_items: dict[str, str]) -> dict[str, str]:
|
|
569
554
|
for file in GeneralUtilities.get_direct_files_of_folder(folder):
|
|
570
555
|
filename = os.path.basename(file)
|
|
@@ -586,10 +571,12 @@ class ScriptCollectionCore:
|
|
|
586
571
|
self.__escape_git_repositories_in_folder_internal(subfolder2, renamed_items)
|
|
587
572
|
return renamed_items
|
|
588
573
|
|
|
574
|
+
@GeneralUtilities.check_arguments
|
|
589
575
|
def deescape_git_repositories_in_folder(self, renamed_items: dict[str, str]):
|
|
590
576
|
for renamed_item, original_name in renamed_items.items():
|
|
591
577
|
os.rename(renamed_item, original_name)
|
|
592
578
|
|
|
579
|
+
@GeneralUtilities.check_arguments
|
|
593
580
|
def __sort_fmd(self, line: str):
|
|
594
581
|
splitted: list = line.split(";")
|
|
595
582
|
filetype: str = splitted[1]
|
|
@@ -626,29 +613,36 @@ class ScriptCollectionCore:
|
|
|
626
613
|
|
|
627
614
|
@GeneralUtilities.check_arguments
|
|
628
615
|
def __calculate_lengh_in_seconds(self, filename: str, folder: str) -> float:
|
|
629
|
-
argument = ['-v', 'error', '-show_entries', 'format=duration',
|
|
630
|
-
'-of', 'default=noprint_wrappers=1:nokey=1', filename]
|
|
616
|
+
argument = ['-v', 'error', '-show_entries', 'format=duration', '-of', 'default=noprint_wrappers=1:nokey=1', filename]
|
|
631
617
|
result = self.run_program_argsasarray("ffprobe", argument, folder, throw_exception_if_exitcode_is_not_zero=True)
|
|
632
618
|
return float(result[1].replace('\n', ''))
|
|
633
619
|
|
|
634
620
|
@GeneralUtilities.check_arguments
|
|
635
|
-
def __create_thumbnails(self, filename: str, fps: str, folder: str, tempname_for_thumbnails: str) ->
|
|
636
|
-
argument = ['-i', filename, '-r', str(fps), '-vf', 'scale=-1:120',
|
|
637
|
-
'-vcodec', 'png', f'{tempname_for_thumbnails}-%002d.png']
|
|
621
|
+
def __create_thumbnails(self, filename: str, fps: str, folder: str, tempname_for_thumbnails: str) -> list[str]:
|
|
622
|
+
argument = ['-i', filename, '-r', str(fps), '-vf', 'scale=-1:120', '-vcodec', 'png', f'{tempname_for_thumbnails}-%002d.png']
|
|
638
623
|
self.run_program_argsasarray("ffmpeg", argument, folder, throw_exception_if_exitcode_is_not_zero=True)
|
|
624
|
+
files = GeneralUtilities.get_direct_files_of_folder(folder)
|
|
625
|
+
result: list[str] = []
|
|
626
|
+
regex = "^"+re.escape(tempname_for_thumbnails)+"\\-\\d+\\.png$"
|
|
627
|
+
regex_for_files = re.compile(regex)
|
|
628
|
+
for file in files:
|
|
629
|
+
filename = os.path.basename(file)
|
|
630
|
+
if regex_for_files.match(filename):
|
|
631
|
+
result.append(file)
|
|
632
|
+
GeneralUtilities.assert_condition(0 < len(result), "No thumbnail-files found.")
|
|
633
|
+
return result
|
|
639
634
|
|
|
640
635
|
@GeneralUtilities.check_arguments
|
|
641
636
|
def __create_thumbnail(self, outputfilename: str, folder: str, length_in_seconds: float, tempname_for_thumbnails: str, amount_of_images: int) -> None:
|
|
642
637
|
duration = timedelta(seconds=length_in_seconds)
|
|
643
638
|
info = GeneralUtilities.timedelta_to_simple_string(duration)
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
self.run_program_argsasarray(
|
|
648
|
-
"montage", argument, folder, throw_exception_if_exitcode_is_not_zero=True)
|
|
639
|
+
rows: int = 5
|
|
640
|
+
columns: int = math.ceil(amount_of_images/rows)
|
|
641
|
+
argument = ['-title', f'"{outputfilename} ({info})"', '-tile', f'{rows}x{columns}', f'{tempname_for_thumbnails}*.png', f'{outputfilename}.png']
|
|
642
|
+
self.run_program_argsasarray("montage", argument, folder, throw_exception_if_exitcode_is_not_zero=True)
|
|
649
643
|
|
|
650
644
|
@GeneralUtilities.check_arguments
|
|
651
|
-
def
|
|
645
|
+
def __roundup(self, x: float, places: int) -> int:
|
|
652
646
|
d = 10 ** places
|
|
653
647
|
if x < 0:
|
|
654
648
|
return math.floor(x * d) / d
|
|
@@ -656,33 +650,35 @@ class ScriptCollectionCore:
|
|
|
656
650
|
return math.ceil(x * d) / d
|
|
657
651
|
|
|
658
652
|
@GeneralUtilities.check_arguments
|
|
659
|
-
def generate_thumbnail(self, file: str, frames_per_second: str, tempname_for_thumbnails: str = None) -> None:
|
|
653
|
+
def generate_thumbnail(self, file: str, frames_per_second: str, tempname_for_thumbnails: str = None, hook=None) -> None:
|
|
660
654
|
if tempname_for_thumbnails is None:
|
|
661
|
-
tempname_for_thumbnails = "
|
|
655
|
+
tempname_for_thumbnails = "t_"+str(uuid.uuid4())
|
|
662
656
|
|
|
663
657
|
file = GeneralUtilities.resolve_relative_path_from_current_working_directory(file)
|
|
664
658
|
filename = os.path.basename(file)
|
|
665
659
|
folder = os.path.dirname(file)
|
|
666
660
|
filename_without_extension = Path(file).stem
|
|
667
|
-
|
|
661
|
+
preview_files: list[str] = []
|
|
668
662
|
try:
|
|
669
663
|
length_in_seconds = self.__calculate_lengh_in_seconds(filename, folder)
|
|
670
664
|
if (frames_per_second.endswith("fps")):
|
|
671
665
|
# frames per second, example: frames_per_second="20fps" => 20 frames per second
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
amounf_of_previewframes = int(math.floor(length_in_seconds*
|
|
666
|
+
frames_per_second = self.__roundup(float(frames_per_second[:-3]), 2)
|
|
667
|
+
frames_per_second_as_string = str(frames_per_second)
|
|
668
|
+
amounf_of_previewframes = int(math.floor(length_in_seconds*frames_per_second))
|
|
675
669
|
else:
|
|
676
670
|
# concrete amount of frame, examples: frames_per_second="16" => 16 frames for entire video
|
|
677
671
|
amounf_of_previewframes = int(float(frames_per_second))
|
|
678
672
|
# self.roundup((amounf_of_previewframes-2)/length_in_seconds, 2)
|
|
679
|
-
|
|
680
|
-
self.__create_thumbnails(filename,
|
|
681
|
-
|
|
673
|
+
frames_per_second_as_string = f"{amounf_of_previewframes-2}/{length_in_seconds}"
|
|
674
|
+
preview_files = self.__create_thumbnails(filename, frames_per_second_as_string, folder, tempname_for_thumbnails)
|
|
675
|
+
if hook is not None:
|
|
676
|
+
hook(file, preview_files)
|
|
677
|
+
actual_amounf_of_previewframes = len(preview_files)
|
|
678
|
+
self.__create_thumbnail(filename_without_extension, folder, length_in_seconds, tempname_for_thumbnails, actual_amounf_of_previewframes)
|
|
682
679
|
finally:
|
|
683
|
-
for thumbnail_to_delete in
|
|
684
|
-
|
|
685
|
-
os.remove(file)
|
|
680
|
+
for thumbnail_to_delete in preview_files:
|
|
681
|
+
os.remove(thumbnail_to_delete)
|
|
686
682
|
|
|
687
683
|
@GeneralUtilities.check_arguments
|
|
688
684
|
def extract_pdf_pages(self, file: str, from_page: int, to_page: int, outputfile: str) -> None:
|
|
@@ -908,29 +904,6 @@ class ScriptCollectionCore:
|
|
|
908
904
|
line[0], line[1], line[2], line[3], line[4])
|
|
909
905
|
GeneralUtilities.write_message_to_stdout(separator_line)
|
|
910
906
|
|
|
911
|
-
@GeneralUtilities.check_arguments
|
|
912
|
-
def SCUploadFileToFileHost(self, file: str, host: str) -> int:
|
|
913
|
-
try:
|
|
914
|
-
GeneralUtilities.write_message_to_stdout(
|
|
915
|
-
self.upload_file_to_file_host(file, host))
|
|
916
|
-
return 0
|
|
917
|
-
except Exception as exception:
|
|
918
|
-
GeneralUtilities.write_exception_to_stderr_with_traceback(exception, traceback)
|
|
919
|
-
return 1
|
|
920
|
-
|
|
921
|
-
@GeneralUtilities.check_arguments
|
|
922
|
-
def SCFileIsAvailableOnFileHost(self, file: str) -> int:
|
|
923
|
-
try:
|
|
924
|
-
if self.file_is_available_on_file_host(file):
|
|
925
|
-
GeneralUtilities.write_message_to_stdout(f"'{file}' is available")
|
|
926
|
-
return 0
|
|
927
|
-
else:
|
|
928
|
-
GeneralUtilities.write_message_to_stdout(f"'{file}' is not available")
|
|
929
|
-
return 1
|
|
930
|
-
except Exception as exception:
|
|
931
|
-
GeneralUtilities.write_exception_to_stderr_with_traceback(exception, traceback)
|
|
932
|
-
return 2
|
|
933
|
-
|
|
934
907
|
@GeneralUtilities.check_arguments
|
|
935
908
|
def SCCalculateBitcoinBlockHash(self, block_version_number: str, previousblockhash: str, transactionsmerkleroot: str, timestamp: str, target: str, nonce: str) -> str:
|
|
936
909
|
# Example-values:
|
|
@@ -1119,44 +1092,6 @@ class ScriptCollectionCore:
|
|
|
1119
1092
|
tor_version = version_with_overhead.split("~")[0]
|
|
1120
1093
|
return tor_version
|
|
1121
1094
|
|
|
1122
|
-
@GeneralUtilities.check_arguments
|
|
1123
|
-
def upload_file_to_file_host(self, file: str, host: str) -> int:
|
|
1124
|
-
if (host is None):
|
|
1125
|
-
return self.upload_file_to_random_filesharing_service(file)
|
|
1126
|
-
elif host == "anonfiles.com":
|
|
1127
|
-
return self.upload_file_to_anonfiles(file)
|
|
1128
|
-
elif host == "bayfiles.com":
|
|
1129
|
-
return self.upload_file_to_bayfiles(file)
|
|
1130
|
-
GeneralUtilities.write_message_to_stderr("Unknown host: "+host)
|
|
1131
|
-
return 1
|
|
1132
|
-
|
|
1133
|
-
@GeneralUtilities.check_arguments
|
|
1134
|
-
def upload_file_to_random_filesharing_service(self, file: str) -> int:
|
|
1135
|
-
host = randrange(2)
|
|
1136
|
-
if host == 0:
|
|
1137
|
-
return self.upload_file_to_anonfiles(file)
|
|
1138
|
-
if host == 1:
|
|
1139
|
-
return self.upload_file_to_bayfiles(file)
|
|
1140
|
-
return 1
|
|
1141
|
-
|
|
1142
|
-
@GeneralUtilities.check_arguments
|
|
1143
|
-
def upload_file_to_anonfiles(self, file) -> int:
|
|
1144
|
-
return self.upload_file_by_using_simple_curl_request("https://api.anonfiles.com/upload", file)
|
|
1145
|
-
|
|
1146
|
-
@GeneralUtilities.check_arguments
|
|
1147
|
-
def upload_file_to_bayfiles(self, file) -> int:
|
|
1148
|
-
return self.upload_file_by_using_simple_curl_request("https://api.bayfiles.com/upload", file)
|
|
1149
|
-
|
|
1150
|
-
@GeneralUtilities.check_arguments
|
|
1151
|
-
def upload_file_by_using_simple_curl_request(self, api_url: str, file: str) -> int:
|
|
1152
|
-
# TODO implement
|
|
1153
|
-
return 1
|
|
1154
|
-
|
|
1155
|
-
@GeneralUtilities.check_arguments
|
|
1156
|
-
def file_is_available_on_file_host(self, file) -> int:
|
|
1157
|
-
# TODO implement
|
|
1158
|
-
return 1
|
|
1159
|
-
|
|
1160
1095
|
def run_testcases_for_python_project(self, repository_folder: str):
|
|
1161
1096
|
self.run_program("coverage", "run -m pytest", repository_folder)
|
|
1162
1097
|
self.run_program("coverage", "xml", repository_folder)
|
|
@@ -1167,7 +1102,7 @@ class ScriptCollectionCore:
|
|
|
1167
1102
|
|
|
1168
1103
|
@GeneralUtilities.check_arguments
|
|
1169
1104
|
def get_file_permission(self, file: str) -> str:
|
|
1170
|
-
"""This function returns an usual octet-triple, for example "
|
|
1105
|
+
"""This function returns an usual octet-triple, for example "700"."""
|
|
1171
1106
|
ls_output = self.__ls(file)
|
|
1172
1107
|
return self.__get_file_permission_helper(ls_output)
|
|
1173
1108
|
|
|
@@ -1210,12 +1145,10 @@ class ScriptCollectionCore:
|
|
|
1210
1145
|
@GeneralUtilities.check_arguments
|
|
1211
1146
|
def __ls(self, file: str) -> str:
|
|
1212
1147
|
file = file.replace("\\", "/")
|
|
1213
|
-
GeneralUtilities.assert_condition(os.path.isfile(file) or os.path.isdir(
|
|
1214
|
-
file), f"Can not execute 'ls' because '{file}' does not exist")
|
|
1148
|
+
GeneralUtilities.assert_condition(os.path.isfile(file) or os.path.isdir(file), f"Can not execute 'ls' because '{file}' does not exist.")
|
|
1215
1149
|
result = self.run_program_argsasarray("ls", ["-ld", file])
|
|
1216
1150
|
GeneralUtilities.assert_condition(result[0] == 0, f"'ls -ld {file}' resulted in exitcode {str(result[0])}. StdErr: {result[2]}")
|
|
1217
|
-
GeneralUtilities.assert_condition(not GeneralUtilities.string_is_none_or_whitespace(
|
|
1218
|
-
result[1]), f"'ls' of '{file}' had an empty output. StdErr: '{result[2]}'")
|
|
1151
|
+
GeneralUtilities.assert_condition(not GeneralUtilities.string_is_none_or_whitespace(result[1]), f"'ls' of '{file}' had an empty output. StdErr: '{result[2]}'")
|
|
1219
1152
|
return result[1]
|
|
1220
1153
|
|
|
1221
1154
|
@GeneralUtilities.check_arguments
|
|
@@ -1255,8 +1188,39 @@ class ScriptCollectionCore:
|
|
|
1255
1188
|
popen: Popen = self.program_runner.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument, interactive)
|
|
1256
1189
|
return popen
|
|
1257
1190
|
|
|
1258
|
-
|
|
1191
|
+
@staticmethod
|
|
1192
|
+
@GeneralUtilities.check_arguments
|
|
1193
|
+
def __enqueue_output(file, queue):
|
|
1194
|
+
for line in iter(file.readline, ''):
|
|
1195
|
+
queue.put(line)
|
|
1196
|
+
file.close()
|
|
1259
1197
|
|
|
1198
|
+
@staticmethod
|
|
1199
|
+
@GeneralUtilities.check_arguments
|
|
1200
|
+
def __read_popen_pipes(p: Popen):
|
|
1201
|
+
|
|
1202
|
+
with ThreadPoolExecutor(2) as pool:
|
|
1203
|
+
q_stdout, q_stderr = Queue(), Queue()
|
|
1204
|
+
|
|
1205
|
+
pool.submit(ScriptCollectionCore.__enqueue_output, p.stdout, q_stdout)
|
|
1206
|
+
pool.submit(ScriptCollectionCore.__enqueue_output, p.stderr, q_stderr)
|
|
1207
|
+
while True:
|
|
1208
|
+
time.sleep(0.2)
|
|
1209
|
+
if p.poll() is not None and q_stdout.empty() and q_stderr.empty():
|
|
1210
|
+
break
|
|
1211
|
+
|
|
1212
|
+
out_line = ''
|
|
1213
|
+
err_line = ''
|
|
1214
|
+
|
|
1215
|
+
try:
|
|
1216
|
+
out_line = q_stdout.get_nowait()
|
|
1217
|
+
err_line = q_stderr.get_nowait()
|
|
1218
|
+
except Empty:
|
|
1219
|
+
pass
|
|
1220
|
+
|
|
1221
|
+
yield (out_line, err_line)
|
|
1222
|
+
|
|
1223
|
+
# Return-values program_runner: Exitcode, StdOut, StdErr, Pid
|
|
1260
1224
|
@GeneralUtilities.check_arguments
|
|
1261
1225
|
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]:
|
|
1262
1226
|
# verbosity 1: No output will be logged.
|
|
@@ -1284,82 +1248,37 @@ class ScriptCollectionCore:
|
|
|
1284
1248
|
|
|
1285
1249
|
if verbosity >= 3:
|
|
1286
1250
|
GeneralUtilities.write_message_to_stdout(f"Run '{info_for_log}'.")
|
|
1251
|
+
|
|
1252
|
+
print_live_output = 1 < verbosity
|
|
1253
|
+
|
|
1254
|
+
exit_code: int = None
|
|
1255
|
+
stdout: str = ""
|
|
1256
|
+
stderr: str = ""
|
|
1257
|
+
pid: int = None
|
|
1258
|
+
|
|
1287
1259
|
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:
|
|
1260
|
+
|
|
1288
1261
|
pid = process.pid
|
|
1262
|
+
for out_line, err_line in ScriptCollectionCore.__read_popen_pipes(process):
|
|
1263
|
+
if print_live_output:
|
|
1264
|
+
#print(out_line, end='')
|
|
1265
|
+
GeneralUtilities.write_message_to_stdout(out_line)
|
|
1266
|
+
#print(err_line, end='')
|
|
1267
|
+
GeneralUtilities.write_message_to_stderr(err_line)
|
|
1289
1268
|
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
log_to_file = log_file is not None
|
|
1296
|
-
if log_to_file:
|
|
1297
|
-
GeneralUtilities.ensure_file_exists(log_file)
|
|
1298
|
-
|
|
1299
|
-
if interactive:
|
|
1300
|
-
# there are 2 issues in this part:
|
|
1301
|
-
# 1.: ctrl+c
|
|
1302
|
-
# 2.: sometimes this function does not terminate even if the started process exited
|
|
1303
|
-
def stream_process(process) -> bool:
|
|
1304
|
-
try:
|
|
1305
|
-
go: bool = process.poll() is None
|
|
1306
|
-
|
|
1307
|
-
stdoutreader: BufferedReader = process.stdout
|
|
1308
|
-
if stdoutreader.readable():
|
|
1309
|
-
stdoutresultb: bytes = stdoutreader.read()
|
|
1310
|
-
stdoutresult = GeneralUtilities.bytes_to_string(
|
|
1311
|
-
stdoutresultb)
|
|
1312
|
-
stdoutlines = GeneralUtilities.string_to_lines(stdoutresult)
|
|
1313
|
-
for line in stdoutlines:
|
|
1314
|
-
line_stripped = line.replace("\r", "").strip()
|
|
1315
|
-
if len(line_stripped) > 0:
|
|
1316
|
-
line_str = line_stripped
|
|
1317
|
-
stdout_lines.append(line_str)
|
|
1318
|
-
if live_console_output_printing:
|
|
1319
|
-
GeneralUtilities.write_message_to_stdout(line_str)
|
|
1320
|
-
if log_to_file:
|
|
1321
|
-
GeneralUtilities.append_line_to_file(
|
|
1322
|
-
log_file, line_str)
|
|
1323
|
-
|
|
1324
|
-
stderrreader: BufferedReader = process.stderr
|
|
1325
|
-
if stderrreader.readable():
|
|
1326
|
-
stderrresultb: bytes = stderrreader.read()
|
|
1327
|
-
stderrresult = GeneralUtilities.bytes_to_string(stderrresultb)
|
|
1328
|
-
stderrlines = GeneralUtilities.string_to_lines(stderrresult)
|
|
1329
|
-
for line in stderrlines:
|
|
1330
|
-
line_stripped = line.replace("\r", "").strip()
|
|
1331
|
-
if len(line_stripped) > 0:
|
|
1332
|
-
line_str = line_stripped
|
|
1333
|
-
stderr_lines.append(line_str)
|
|
1334
|
-
if live_console_output_printing:
|
|
1335
|
-
if print_errors_as_information:
|
|
1336
|
-
GeneralUtilities.write_message_to_stdout(line_str)
|
|
1337
|
-
else:
|
|
1338
|
-
GeneralUtilities.write_message_to_stderr(line_str)
|
|
1339
|
-
if log_to_file:
|
|
1340
|
-
GeneralUtilities.append_line_to_file(log_file, line_str)
|
|
1341
|
-
|
|
1342
|
-
return go
|
|
1343
|
-
except Exception:
|
|
1344
|
-
return False
|
|
1345
|
-
|
|
1346
|
-
while stream_process(process):
|
|
1347
|
-
time.sleep(0.1)
|
|
1348
|
-
|
|
1349
|
-
exit_code = process.poll()
|
|
1350
|
-
stdout = '\n'.join(stdout_lines)
|
|
1351
|
-
stderr = '\n'.join(stderr_lines)
|
|
1352
|
-
else:
|
|
1353
|
-
stdout, stderr = process.communicate()
|
|
1354
|
-
exit_code = process.wait()
|
|
1355
|
-
stdout = GeneralUtilities.bytes_to_string(stdout).replace('\r', '')
|
|
1356
|
-
stderr = GeneralUtilities.bytes_to_string(stderr).replace('\r', '')
|
|
1269
|
+
if out_line is not None and GeneralUtilities.string_has_content(out_line):
|
|
1270
|
+
stdout = stdout+"\n"+out_line
|
|
1271
|
+
if err_line is not None and GeneralUtilities.string_has_content(err_line):
|
|
1272
|
+
stderr = stderr+"\n"+err_line
|
|
1357
1273
|
|
|
1358
|
-
|
|
1359
|
-
|
|
1274
|
+
process.poll()
|
|
1275
|
+
exit_code = process.returncode
|
|
1360
1276
|
|
|
1361
|
-
|
|
1362
|
-
|
|
1277
|
+
if throw_exception_if_exitcode_is_not_zero and exit_code != 0:
|
|
1278
|
+
raise ValueError(f"Program '{working_directory}>{program} {arguments_for_log_as_string}' resulted in exitcode {exit_code}. (StdOut: '{stdout}', StdErr: '{stderr}')")
|
|
1279
|
+
|
|
1280
|
+
result = (exit_code, stdout, stderr, pid)
|
|
1281
|
+
return result
|
|
1363
1282
|
except Exception as e:
|
|
1364
1283
|
raise e
|
|
1365
1284
|
|
|
@@ -1516,8 +1435,7 @@ class ScriptCollectionCore:
|
|
|
1516
1435
|
result = self.get_version_from_gitversion(repository_folder, "MajorMinorPatch")
|
|
1517
1436
|
if self.git_repository_has_uncommitted_changes(repository_folder):
|
|
1518
1437
|
if self.get_current_git_branch_has_tag(repository_folder):
|
|
1519
|
-
id_of_latest_tag = self.git_get_commitid_of_tag(
|
|
1520
|
-
repository_folder, self.get_latest_git_tag(repository_folder))
|
|
1438
|
+
id_of_latest_tag = self.git_get_commitid_of_tag(repository_folder, self.get_latest_git_tag(repository_folder))
|
|
1521
1439
|
current_commit = self.git_get_commit_id(repository_folder)
|
|
1522
1440
|
current_commit_is_on_latest_tag = id_of_latest_tag == current_commit
|
|
1523
1441
|
if current_commit_is_on_latest_tag:
|
|
@@ -1560,8 +1478,7 @@ class ScriptCollectionCore:
|
|
|
1560
1478
|
self.run_program("openssl", f'genrsa -out {filename}.key {rsa_key_length}', folder)
|
|
1561
1479
|
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)
|
|
1562
1480
|
self.run_program("openssl", f'pkcs12 -export -out {filename}.selfsigned.pfx -password pass:{password} -inkey {filename}.key -in {filename}.unsigned.crt', folder)
|
|
1563
|
-
GeneralUtilities.write_text_to_file(
|
|
1564
|
-
os.path.join(folder, f"{filename}.password"), password)
|
|
1481
|
+
GeneralUtilities.write_text_to_file(os.path.join(folder, f"{filename}.password"), password)
|
|
1565
1482
|
GeneralUtilities.write_text_to_file(os.path.join(folder, f"{filename}.san.conf"), f"""[ req ]
|
|
1566
1483
|
default_bits = {rsa_key_length}
|
|
1567
1484
|
distinguished_name = req_distinguished_name
|
|
@@ -1587,8 +1504,7 @@ DNS = {domain}
|
|
|
1587
1504
|
|
|
1588
1505
|
@GeneralUtilities.check_arguments
|
|
1589
1506
|
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:
|
|
1590
|
-
self.run_program(
|
|
1591
|
-
"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)
|
|
1507
|
+
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)
|
|
1592
1508
|
|
|
1593
1509
|
@GeneralUtilities.check_arguments
|
|
1594
1510
|
def sign_certificate(self, folder: str, ca_folder: str, ca_name: str, domain: str, filename: str, days_until_expire: int = None) -> None:
|
|
@@ -1616,11 +1532,13 @@ DNS = {domain}
|
|
|
1616
1532
|
elif ">" in line:
|
|
1617
1533
|
try:
|
|
1618
1534
|
# line is something like "cyclonedx-bom>=2.0.2" and the function must return with the updated version
|
|
1619
|
-
# (something like "cyclonedx-bom>=
|
|
1535
|
+
# (something like "cyclonedx-bom>=2.11.0" for example)
|
|
1620
1536
|
package = line.split(">")[0]
|
|
1621
1537
|
operator = ">=" if ">=" in line else ">"
|
|
1622
1538
|
response = requests.get(f'https://pypi.org/pypi/{package}/json', timeout=5)
|
|
1623
1539
|
latest_version = response.json()['info']['version']
|
|
1540
|
+
# TODO update only minor- and patch-version
|
|
1541
|
+
# TODO print info if there is a new major-version
|
|
1624
1542
|
return package+operator+latest_version
|
|
1625
1543
|
except:
|
|
1626
1544
|
return line
|
|
@@ -1683,8 +1601,7 @@ DNS = {domain}
|
|
|
1683
1601
|
GeneralUtilities.ensure_directory_exists(packagecontent_entireresult_folder)
|
|
1684
1602
|
|
|
1685
1603
|
# create "debian-binary"-file
|
|
1686
|
-
debianbinary_file = os.path.join(
|
|
1687
|
-
packagecontent_entireresult_folder, "debian-binary")
|
|
1604
|
+
debianbinary_file = os.path.join(packagecontent_entireresult_folder, "debian-binary")
|
|
1688
1605
|
GeneralUtilities.ensure_file_exists(debianbinary_file)
|
|
1689
1606
|
GeneralUtilities.write_text_to_file(debianbinary_file, "2.0\n")
|
|
1690
1607
|
|
|
@@ -1701,10 +1618,10 @@ DNS = {domain}
|
|
|
1701
1618
|
link_file = f"/usr/bin/{toolname.lower()}"
|
|
1702
1619
|
permission = str(permission_of_executable_file_as_octet_triple)
|
|
1703
1620
|
GeneralUtilities.write_text_to_file(postinst_file, f"""#!/bin/sh
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1621
|
+
ln -s {exe_file} {link_file}
|
|
1622
|
+
chmod {permission} {exe_file}
|
|
1623
|
+
chmod {permission} {link_file}
|
|
1624
|
+
""")
|
|
1708
1625
|
|
|
1709
1626
|
# control
|
|
1710
1627
|
control_file = os.path.join(packagecontent_control_folder, "control")
|
|
@@ -1775,24 +1692,22 @@ DNS = {domain}
|
|
|
1775
1692
|
proxies = None
|
|
1776
1693
|
if GeneralUtilities.string_has_content(proxy):
|
|
1777
1694
|
proxies = {"http": proxy}
|
|
1778
|
-
response = requests.get('https://ipinfo.io',
|
|
1779
|
-
proxies=proxies, timeout=5)
|
|
1695
|
+
response = requests.get('https://ipinfo.io', proxies=proxies, timeout=5)
|
|
1780
1696
|
network_information_as_json_string = GeneralUtilities.bytes_to_string(
|
|
1781
1697
|
response.content)
|
|
1782
1698
|
return network_information_as_json_string
|
|
1783
1699
|
|
|
1784
1700
|
@GeneralUtilities.check_arguments
|
|
1785
1701
|
def change_file_extensions(self, folder: str, from_extension: str, to_extension: str, recursive: bool, ignore_case: bool) -> None:
|
|
1786
|
-
extension_to_compare:str=None
|
|
1702
|
+
extension_to_compare: str = None
|
|
1787
1703
|
if ignore_case:
|
|
1788
|
-
extension_to_compare=from_extension.lower()
|
|
1704
|
+
extension_to_compare = from_extension.lower()
|
|
1789
1705
|
else:
|
|
1790
|
-
extension_to_compare=from_extension
|
|
1706
|
+
extension_to_compare = from_extension
|
|
1791
1707
|
for file in GeneralUtilities.get_direct_files_of_folder(folder):
|
|
1792
|
-
if (ignore_case and file.lower().endswith(f".{extension_to_compare}")
|
|
1793
|
-
or not ignore_case and file.endswith(f".{extension_to_compare}")):
|
|
1708
|
+
if (ignore_case and file.lower().endswith(f".{extension_to_compare}") or not ignore_case and file.endswith(f".{extension_to_compare}")):
|
|
1794
1709
|
p = Path(file)
|
|
1795
1710
|
p.rename(p.with_suffix('.'+to_extension))
|
|
1796
1711
|
if recursive:
|
|
1797
1712
|
for subfolder in GeneralUtilities.get_direct_folders_of_folder(folder):
|
|
1798
|
-
self.change_file_extensions(subfolder, from_extension, to_extension, recursive,ignore_case)
|
|
1713
|
+
self.change_file_extensions(subfolder, from_extension, to_extension, recursive, ignore_case)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
ScriptCollection/Executables.py,sha256=msAlVLjgrxCxW-5Uu7Gk8NI1CNQLK2i6TjNR1fppaCY,19535
|
|
2
|
-
ScriptCollection/GeneralUtilities.py,sha256=
|
|
2
|
+
ScriptCollection/GeneralUtilities.py,sha256=AElXv2NO30cTw-Qs3qVmO-YCOQ5FvBQM3RZMywuKQ_Y,35121
|
|
3
3
|
ScriptCollection/ProcessesRunner.py,sha256=3mu4ZxzZleQo0Op6o9EYTCFiJfb6kx5ov2YfZfT89mU,1395
|
|
4
4
|
ScriptCollection/ProgramRunnerBase.py,sha256=7QAjoqOz6XPmJH19F2k-Z1fFQB_uZnPFvn-T54IJcHQ,2324
|
|
5
5
|
ScriptCollection/ProgramRunnerEpew.py,sha256=C2Rs3YWOWWWJct7XmKphp5CF1tf0j4Fp-ljV2drLTfs,6349
|
|
6
|
-
ScriptCollection/ProgramRunnerPopen.py,sha256=
|
|
6
|
+
ScriptCollection/ProgramRunnerPopen.py,sha256=G3LgQUVCfaq7XjBsGzalElH31Hbr0etttGR2_H87YzA,3512
|
|
7
7
|
ScriptCollection/RPStream.py,sha256=NRRHL3YSP3D9MuAV2jB_--0KUKCsvJGxeKnxgrRZ9kY,1545
|
|
8
|
-
ScriptCollection/ScriptCollectionCore.py,sha256=
|
|
8
|
+
ScriptCollection/ScriptCollectionCore.py,sha256=na1wwDDpUOZAyIqPREH5MeCn1IJfYvN0NEm-YeViCdE,92720
|
|
9
9
|
ScriptCollection/TasksForCommonProjectStructure.py,sha256=-QxOB01yFHrcPpTNnDA0GY0rv9McvQ95DZ3PNHRCrFE,184090
|
|
10
10
|
ScriptCollection/UpdateCertificates.py,sha256=Eynbgu7k9jLxApP2D_8Il77B6BFjJap6K7oTeEAZYbk,7790
|
|
11
11
|
ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
ScriptCollection-3.5.
|
|
13
|
-
ScriptCollection-3.5.
|
|
14
|
-
ScriptCollection-3.5.
|
|
15
|
-
ScriptCollection-3.5.
|
|
16
|
-
ScriptCollection-3.5.
|
|
12
|
+
ScriptCollection-3.5.14.dist-info/METADATA,sha256=e_vy24P8qOOWX0xn2ds4jO7IrEojsfAR4c5pCa1FcgM,7680
|
|
13
|
+
ScriptCollection-3.5.14.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
14
|
+
ScriptCollection-3.5.14.dist-info/entry_points.txt,sha256=Jz1pyS3Q6lqpuOWVHogt00jGwrpcHYtPrHGY0_Ltjbo,2227
|
|
15
|
+
ScriptCollection-3.5.14.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
|
|
16
|
+
ScriptCollection-3.5.14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|