ScriptCollection 3.5.84__py3-none-any.whl → 3.5.86__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/Executables.py +19 -18
- ScriptCollection/ScriptCollectionCore.py +55 -60
- ScriptCollection/TasksForCommonProjectStructure.py +24 -14
- {ScriptCollection-3.5.84.dist-info → scriptcollection-3.5.86.dist-info}/METADATA +2 -2
- {ScriptCollection-3.5.84.dist-info → scriptcollection-3.5.86.dist-info}/RECORD +8 -8
- {ScriptCollection-3.5.84.dist-info → scriptcollection-3.5.86.dist-info}/WHEEL +1 -1
- {ScriptCollection-3.5.84.dist-info → scriptcollection-3.5.86.dist-info}/entry_points.txt +0 -0
- {ScriptCollection-3.5.84.dist-info → scriptcollection-3.5.86.dist-info}/top_level.txt +0 -0
ScriptCollection/Executables.py
CHANGED
@@ -379,6 +379,7 @@ def CreateChangelogEntry() -> int:
|
|
379
379
|
parser.add_argument('-f', '--repositoryfolder', required=False, default=".")
|
380
380
|
parser.add_argument('-m', '--message', required=False, default="Updates.")
|
381
381
|
parser.add_argument('-c', '--commit', action='store_true', required=False, default=False)
|
382
|
+
parser.add_argument('-f', '--force', action='store_true', required=False, default=False)
|
382
383
|
args = parser.parse_args()
|
383
384
|
|
384
385
|
folder: str = None
|
@@ -386,7 +387,7 @@ def CreateChangelogEntry() -> int:
|
|
386
387
|
folder = args.repositoryfolder
|
387
388
|
else:
|
388
389
|
folder = GeneralUtilities.resolve_relative_path(args.repositoryfolder, os.getcwd())
|
389
|
-
TasksForCommonProjectStructure().create_changelog_entry(folder, args.message, args.commit)
|
390
|
+
TasksForCommonProjectStructure().create_changelog_entry(folder, args.message, args.commit, args.force)
|
390
391
|
return 0
|
391
392
|
|
392
393
|
|
@@ -538,18 +539,18 @@ def Copy() -> int:
|
|
538
539
|
if os.path.isfile(args.target) or os.path.isdir(args.target):
|
539
540
|
raise ValueError(f"Can not copy to '{args.target}' because the target already exists.")
|
540
541
|
|
541
|
-
source=args.source
|
542
|
+
source = args.source
|
542
543
|
if not os.path.isabs(source):
|
543
|
-
source=GeneralUtilities.resolve_relative_path(source,os.getcwd())
|
544
|
-
target=args.target
|
544
|
+
source = GeneralUtilities.resolve_relative_path(source, os.getcwd())
|
545
|
+
target = args.target
|
545
546
|
if not os.path.isabs(target):
|
546
|
-
target=GeneralUtilities.resolve_relative_path(target,os.getcwd())
|
547
|
+
target = GeneralUtilities.resolve_relative_path(target, os.getcwd())
|
547
548
|
|
548
549
|
if os.path.isfile(source):
|
549
550
|
shutil.copyfile(source, target)
|
550
551
|
elif os.path.isdir(source):
|
551
552
|
GeneralUtilities.ensure_directory_exists(target)
|
552
|
-
GeneralUtilities.copy_content_of_folder(source,target)
|
553
|
+
GeneralUtilities.copy_content_of_folder(source, target)
|
553
554
|
else:
|
554
555
|
raise ValueError(f"'{source}' can not be copied because the path does not exist.")
|
555
556
|
return 0
|
@@ -575,26 +576,26 @@ def PrintCurrecntWorkingDirectory() -> int:
|
|
575
576
|
def ListFolderContent() -> int:
|
576
577
|
parser = argparse.ArgumentParser(description="This function lists folder-content.")
|
577
578
|
parser.add_argument('-p', '--path', required=True)
|
578
|
-
parser.add_argument('-f', '--excludefiles', action='store_true', required=False,default=False)
|
579
|
-
parser.add_argument('-d', '--excludedirectories', action='store_true', required=False,default=False)
|
580
|
-
parser.add_argument('-n', '--printonlynamewithoutpath', action='store_true', required=False,default=False)
|
579
|
+
parser.add_argument('-f', '--excludefiles', action='store_true', required=False, default=False)
|
580
|
+
parser.add_argument('-d', '--excludedirectories', action='store_true', required=False, default=False)
|
581
|
+
parser.add_argument('-n', '--printonlynamewithoutpath', action='store_true', required=False, default=False)
|
581
582
|
# TODO add option to also list transitively list subfolder
|
582
583
|
# TODO add option to show only content which matches a filter by extension or regex or glob-pattern
|
583
|
-
args=parser.parse_args()
|
584
|
-
folder=args.path
|
584
|
+
args = parser.parse_args()
|
585
|
+
folder = args.path
|
585
586
|
if not os.path.isabs(folder):
|
586
|
-
folder=GeneralUtilities.resolve_relative_path(folder,os.getcwd())
|
587
|
-
content=[]
|
587
|
+
folder = GeneralUtilities.resolve_relative_path(folder, os.getcwd())
|
588
|
+
content = []
|
588
589
|
if not args.excludefiles:
|
589
|
-
content=content+GeneralUtilities.get_direct_files_of_folder(folder)
|
590
|
+
content = content+GeneralUtilities.get_direct_files_of_folder(folder)
|
590
591
|
if not args.excludedirectories:
|
591
|
-
content=content+GeneralUtilities.get_direct_folders_of_folder(folder)
|
592
|
+
content = content+GeneralUtilities.get_direct_folders_of_folder(folder)
|
592
593
|
for contentitem in content:
|
593
|
-
content_to_print:str=None
|
594
|
+
content_to_print: str = None
|
594
595
|
if args.printonlynamewithoutpath:
|
595
|
-
content_to_print=os.path.basename(contentitem)
|
596
|
+
content_to_print = os.path.basename(contentitem)
|
596
597
|
else:
|
597
|
-
content_to_print= contentitem
|
598
|
+
content_to_print = contentitem
|
598
599
|
GeneralUtilities.write_message_to_stdout(content_to_print)
|
599
600
|
return 0
|
600
601
|
|
@@ -32,7 +32,7 @@ from .ProgramRunnerBase import ProgramRunnerBase
|
|
32
32
|
from .ProgramRunnerPopen import ProgramRunnerPopen
|
33
33
|
from .ProgramRunnerEpew import ProgramRunnerEpew, CustomEpewArgument
|
34
34
|
|
35
|
-
version = "3.5.
|
35
|
+
version = "3.5.86"
|
36
36
|
__version__ = version
|
37
37
|
|
38
38
|
|
@@ -192,7 +192,7 @@ class ScriptCollectionCore:
|
|
192
192
|
until_as_string = self.__datetime_to_string_for_git(until)
|
193
193
|
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", ""))
|
194
194
|
if ignore_commits_which_are_not_in_history_of_head:
|
195
|
-
result = [commit_id for commit_id in result if self.git_commit_is_ancestor(
|
195
|
+
result = [commit_id for commit_id in result if self.git_commit_is_ancestor(repository_folder, commit_id)]
|
196
196
|
return result
|
197
197
|
|
198
198
|
@GeneralUtilities.check_arguments
|
@@ -303,7 +303,7 @@ class ScriptCollectionCore:
|
|
303
303
|
|
304
304
|
@GeneralUtilities.check_arguments
|
305
305
|
def git_pull_with_retry(self, folder: str, remote: str, localbranchname: str, remotebranchname: str, force: bool = False, amount_of_attempts: int = 5) -> None:
|
306
|
-
GeneralUtilities.retry_action(lambda: self.git_pull_with_retry(folder, remote,localbranchname,remotebranchname), amount_of_attempts)
|
306
|
+
GeneralUtilities.retry_action(lambda: self.git_pull_with_retry(folder, remote, localbranchname, remotebranchname), amount_of_attempts)
|
307
307
|
|
308
308
|
@GeneralUtilities.check_arguments
|
309
309
|
def git_pull(self, folder: str, remote: str, localbranchname: str, remotebranchname: str, force: bool = False) -> None:
|
@@ -381,7 +381,7 @@ class ScriptCollectionCore:
|
|
381
381
|
def git_unstage_all_changes(self, directory: str) -> None:
|
382
382
|
self.assert_is_git_repository(directory)
|
383
383
|
self.run_program_argsasarray("git", ["reset"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
384
|
-
#TODO check if this will also be done for submodules
|
384
|
+
# TODO check if this will also be done for submodules
|
385
385
|
|
386
386
|
@GeneralUtilities.check_arguments
|
387
387
|
def git_stage_file(self, directory: str, file: str) -> None:
|
@@ -405,10 +405,10 @@ class ScriptCollectionCore:
|
|
405
405
|
self.assert_is_git_repository(directory)
|
406
406
|
self.run_program_argsasarray("git", ['clean', '-df'], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
407
407
|
self.run_program_argsasarray("git", ['checkout', '.'], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
408
|
-
#TODO check if this will also be done for submodules
|
408
|
+
# TODO check if this will also be done for submodules
|
409
409
|
|
410
410
|
@GeneralUtilities.check_arguments
|
411
|
-
def git_commit(self, directory: str, message: str="Saved changes.", author_name: str = None, author_email: str = None, stage_all_changes: bool = True, no_changes_behavior: int = 0) -> str:
|
411
|
+
def git_commit(self, directory: str, message: str = "Saved changes.", author_name: str = None, author_email: str = None, stage_all_changes: bool = True, no_changes_behavior: int = 0) -> str:
|
412
412
|
"""no_changes_behavior=0 => No commit; no_changes_behavior=1 => Commit anyway; no_changes_behavior=2 => Exception"""
|
413
413
|
self.assert_is_git_repository(directory)
|
414
414
|
author_name = GeneralUtilities.str_none_safe(author_name).strip()
|
@@ -448,7 +448,7 @@ class ScriptCollectionCore:
|
|
448
448
|
if message is None:
|
449
449
|
message = f"Created {target_for_tag}"
|
450
450
|
argument.extend(["-s", '-m', message])
|
451
|
-
self.run_program_argsasarray(
|
451
|
+
self.run_program_argsasarray("git", argument, directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
452
452
|
|
453
453
|
@GeneralUtilities.check_arguments
|
454
454
|
def git_delete_tag(self, directory: str, tag: str) -> None:
|
@@ -456,9 +456,10 @@ class ScriptCollectionCore:
|
|
456
456
|
self.run_program_argsasarray("git", ["tag", "--delete", tag], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
457
457
|
|
458
458
|
@GeneralUtilities.check_arguments
|
459
|
-
def git_checkout(self, directory: str, branch: str,undo_all_changes_after_checkout:bool=True) -> None:
|
459
|
+
def git_checkout(self, directory: str, branch: str, undo_all_changes_after_checkout: bool = True, assert_no_uncommitted_changes: bool = True) -> None:
|
460
460
|
self.assert_is_git_repository(directory)
|
461
|
-
|
461
|
+
if assert_no_uncommitted_changes:
|
462
|
+
GeneralUtilities.assert_condition(not self.git_repository_has_uncommitted_changes(directory), f"Repository '{directory}' has uncommitted changes.")
|
462
463
|
self.run_program_argsasarray("git", ["checkout", branch], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
463
464
|
self.run_program_argsasarray("git", ["submodule", "update", "--recursive"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
464
465
|
if undo_all_changes_after_checkout:
|
@@ -470,9 +471,9 @@ class ScriptCollectionCore:
|
|
470
471
|
self.run_program_argsasarray("git", ["merge", "--abort"], directory, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
471
472
|
|
472
473
|
@GeneralUtilities.check_arguments
|
473
|
-
def git_merge(self, directory: str, sourcebranch: str, targetbranch: str, fastforward: bool = True, commit: bool = True, commit_message: str = None) -> str:
|
474
|
+
def git_merge(self, directory: str, sourcebranch: str, targetbranch: str, fastforward: bool = True, commit: bool = True, commit_message: str = None, undo_all_changes_after_checkout: bool = True, assert_no_uncommitted_changes: bool = True) -> str:
|
474
475
|
self.assert_is_git_repository(directory)
|
475
|
-
self.git_checkout(directory, targetbranch)
|
476
|
+
self.git_checkout(directory, targetbranch, undo_all_changes_after_checkout, assert_no_uncommitted_changes)
|
476
477
|
args = ["merge"]
|
477
478
|
if not commit:
|
478
479
|
args.append("--no-commit")
|
@@ -662,28 +663,28 @@ class ScriptCollectionCore:
|
|
662
663
|
GeneralUtilities.assert_condition(self.is_git_repository(folder), f"'{folder}' is not a git-repository.")
|
663
664
|
|
664
665
|
@GeneralUtilities.check_arguments
|
665
|
-
def list_content(self, path: str,include_files:bool,include_folder:bool,printonlynamewithoutpath:bool) -> list[str]:
|
666
|
+
def list_content(self, path: str, include_files: bool, include_folder: bool, printonlynamewithoutpath: bool) -> list[str]:
|
666
667
|
"""This function works platform-independent also for non-local-executions if the ScriptCollection commandline-commands are available as global command on the target-system."""
|
667
668
|
if self.program_runner.will_be_executed_locally():
|
668
|
-
result=[]
|
669
|
+
result = []
|
669
670
|
if include_files:
|
670
|
-
result=result + GeneralUtilities.get_direct_files_of_folder(path)
|
671
|
+
result = result + GeneralUtilities.get_direct_files_of_folder(path)
|
671
672
|
if include_folder:
|
672
|
-
result=result + GeneralUtilities.get_direct_folders_of_folder(path)
|
673
|
+
result = result + GeneralUtilities.get_direct_folders_of_folder(path)
|
673
674
|
return result
|
674
675
|
else:
|
675
|
-
arguments=["--path", path]
|
676
|
+
arguments = ["--path", path]
|
676
677
|
if not include_files:
|
677
|
-
arguments=arguments+["--excludefiles"]
|
678
|
+
arguments = arguments+["--excludefiles"]
|
678
679
|
if not include_folder:
|
679
|
-
arguments=arguments+["--excludedirectories"]
|
680
|
+
arguments = arguments+["--excludedirectories"]
|
680
681
|
if printonlynamewithoutpath:
|
681
|
-
arguments=arguments+["--printonlynamewithoutpath"]
|
682
|
+
arguments = arguments+["--printonlynamewithoutpath"]
|
682
683
|
exit_code, stdout, stderr, _ = self.run_program_argsasarray("sclistfoldercontent", arguments)
|
683
684
|
if exit_code == 0:
|
684
|
-
result:list[str]=[]
|
685
|
+
result: list[str] = []
|
685
686
|
for line in stdout.split("\n"):
|
686
|
-
normalized_line=line.replace("\r","")
|
687
|
+
normalized_line = line.replace("\r", "")
|
687
688
|
result.append(normalized_line)
|
688
689
|
return result
|
689
690
|
else:
|
@@ -720,7 +721,7 @@ class ScriptCollectionCore:
|
|
720
721
|
raise ValueError(f"Fatal error occurrs while checking whether folder '{path}' exists. StdErr: '{stderr}'")
|
721
722
|
|
722
723
|
@GeneralUtilities.check_arguments
|
723
|
-
def remove(self, path: str) ->None:
|
724
|
+
def remove(self, path: str) -> None:
|
724
725
|
"""This function works platform-independent also for non-local-executions if the ScriptCollection commandline-commands are available as global command on the target-system."""
|
725
726
|
if self.program_runner.will_be_executed_locally(): # works only locally, but much more performant than always running an external program
|
726
727
|
if os.path.isdir(path):
|
@@ -738,17 +739,17 @@ class ScriptCollectionCore:
|
|
738
739
|
raise ValueError(f"Fatal error occurrs while removing folder '{path}'. StdErr: '{stderr}'")
|
739
740
|
|
740
741
|
@GeneralUtilities.check_arguments
|
741
|
-
def rename(self, source:str,target:str) ->None:
|
742
|
+
def rename(self, source: str, target: str) -> None:
|
742
743
|
"""This function works platform-independent also for non-local-executions if the ScriptCollection commandline-commands are available as global command on the target-system."""
|
743
744
|
if self.program_runner.will_be_executed_locally(): # works only locally, but much more performant than always running an external program
|
744
745
|
os.rename(source, target)
|
745
746
|
else:
|
746
|
-
exit_code, _, stderr, _ = self.run_program_argsasarray("screname", ["--source", source,"--target",target], throw_exception_if_exitcode_is_not_zero=False) # works platform-indepent
|
747
|
+
exit_code, _, stderr, _ = self.run_program_argsasarray("screname", ["--source", source, "--target", target], throw_exception_if_exitcode_is_not_zero=False) # works platform-indepent
|
747
748
|
if exit_code != 0:
|
748
749
|
raise ValueError(f"Fatal error occurrs while renaming '{source}' to '{target}'. StdErr: '{stderr}'")
|
749
750
|
|
750
751
|
@GeneralUtilities.check_arguments
|
751
|
-
def copy(self, source:str,target:str) ->None:
|
752
|
+
def copy(self, source: str, target: str) -> None:
|
752
753
|
"""This function works platform-independent also for non-local-executions if the ScriptCollection commandline-commands are available as global command on the target-system."""
|
753
754
|
if self.program_runner.will_be_executed_locally(): # works only locally, but much more performant than always running an external program
|
754
755
|
if os.path.isfile(target) or os.path.isdir(target):
|
@@ -757,11 +758,11 @@ class ScriptCollectionCore:
|
|
757
758
|
shutil.copyfile(source, target)
|
758
759
|
elif os.path.isdir(source):
|
759
760
|
GeneralUtilities.ensure_directory_exists(target)
|
760
|
-
GeneralUtilities.copy_content_of_folder(source,target)
|
761
|
+
GeneralUtilities.copy_content_of_folder(source, target)
|
761
762
|
else:
|
762
763
|
raise ValueError(f"'{source}' can not be copied because the path does not exist.")
|
763
764
|
else:
|
764
|
-
exit_code, _, stderr, _ = self.run_program_argsasarray("sccopy", ["--source", source,"--target", target], throw_exception_if_exitcode_is_not_zero=False) # works platform-indepent
|
765
|
+
exit_code, _, stderr, _ = self.run_program_argsasarray("sccopy", ["--source", source, "--target", target], throw_exception_if_exitcode_is_not_zero=False) # works platform-indepent
|
765
766
|
if exit_code != 0:
|
766
767
|
raise ValueError(f"Fatal error occurrs while copying '{source}' to '{target}'. StdErr: '{stderr}'")
|
767
768
|
|
@@ -1086,14 +1087,11 @@ class ScriptCollectionCore:
|
|
1086
1087
|
|
1087
1088
|
@GeneralUtilities.check_arguments
|
1088
1089
|
def SCShow2FAAsQRCode(self, csvfile: str) -> None:
|
1089
|
-
separator_line = "--------------------------------------------------------"
|
1090
1090
|
lines = GeneralUtilities.read_csv_file(csvfile, True)
|
1091
1091
|
lines.sort(key=lambda items: ''.join(items).lower())
|
1092
1092
|
for line in lines:
|
1093
|
-
|
1094
|
-
|
1095
|
-
line[0], line[1], line[2], line[3], line[4])
|
1096
|
-
GeneralUtilities.write_message_to_stdout(separator_line)
|
1093
|
+
self.__print_qr_code_by_csv_line(line[0], line[1], line[2], line[3], line[4])
|
1094
|
+
GeneralUtilities.write_message_to_stdout(GeneralUtilities.get_longline())
|
1097
1095
|
|
1098
1096
|
@GeneralUtilities.check_arguments
|
1099
1097
|
def SCCalculateBitcoinBlockHash(self, block_version_number: str, previousblockhash: str, transactionsmerkleroot: str, timestamp: str, target: str, nonce: str) -> str:
|
@@ -1381,7 +1379,7 @@ class ScriptCollectionCore:
|
|
1381
1379
|
return popen
|
1382
1380
|
|
1383
1381
|
@staticmethod
|
1384
|
-
def __enqueue_output(file:IO, queue:Queue):
|
1382
|
+
def __enqueue_output(file: IO, queue: Queue):
|
1385
1383
|
for line in iter(file.readline, ''):
|
1386
1384
|
queue.put(line)
|
1387
1385
|
file.close()
|
@@ -1403,7 +1401,7 @@ class ScriptCollectionCore:
|
|
1403
1401
|
return False
|
1404
1402
|
|
1405
1403
|
@staticmethod
|
1406
|
-
def __read_popen_pipes(p: Popen,print_live_output:bool,print_errors_as_information:bool) -> tuple[list[str], list[str]]:
|
1404
|
+
def __read_popen_pipes(p: Popen, print_live_output: bool, print_errors_as_information: bool) -> tuple[list[str], list[str]]:
|
1407
1405
|
p_id = p.pid
|
1408
1406
|
with ThreadPoolExecutor(2) as pool:
|
1409
1407
|
q_stdout = Queue()
|
@@ -1420,8 +1418,8 @@ class ScriptCollectionCore:
|
|
1420
1418
|
while (ScriptCollectionCore.__continue_process_reading(p_id, p, q_stdout, q_stderr, reading_stdout_last_time_resulted_in_exception, reading_stderr_last_time_resulted_in_exception)):
|
1421
1419
|
try:
|
1422
1420
|
while not q_stdout.empty():
|
1423
|
-
out_line:str=q_stdout.get_nowait()
|
1424
|
-
out_line=out_line.replace("\r","").replace("\n","")
|
1421
|
+
out_line: str = q_stdout.get_nowait()
|
1422
|
+
out_line = out_line.replace("\r", "").replace("\n", "")
|
1425
1423
|
if GeneralUtilities.string_has_content(out_line):
|
1426
1424
|
stdout_result.append(out_line)
|
1427
1425
|
reading_stdout_last_time_resulted_in_exception = False
|
@@ -1434,8 +1432,8 @@ class ScriptCollectionCore:
|
|
1434
1432
|
|
1435
1433
|
try:
|
1436
1434
|
while not q_stderr.empty():
|
1437
|
-
err_line:str=q_stderr.get_nowait()
|
1438
|
-
err_line=err_line.replace("\r","").replace("\n","")
|
1435
|
+
err_line: str = q_stderr.get_nowait()
|
1436
|
+
err_line = err_line.replace("\r", "").replace("\n", "")
|
1439
1437
|
if GeneralUtilities.string_has_content(err_line):
|
1440
1438
|
stderr_result.append(err_line)
|
1441
1439
|
reading_stderr_last_time_resulted_in_exception = False
|
@@ -1493,7 +1491,7 @@ class ScriptCollectionCore:
|
|
1493
1491
|
GeneralUtilities.ensure_file_exists(log_file)
|
1494
1492
|
pid = process.pid
|
1495
1493
|
|
1496
|
-
outputs: tuple[list[str], list[str]] = ScriptCollectionCore.__read_popen_pipes(process,print_live_output,print_errors_as_information)
|
1494
|
+
outputs: tuple[list[str], list[str]] = ScriptCollectionCore.__read_popen_pipes(process, print_live_output, print_errors_as_information)
|
1497
1495
|
|
1498
1496
|
for out_line_plain in outputs[0]:
|
1499
1497
|
if out_line_plain is not None:
|
@@ -1550,8 +1548,8 @@ class ScriptCollectionCore:
|
|
1550
1548
|
|
1551
1549
|
# Return-values program_runner: Exitcode, StdOut, StdErr, Pid
|
1552
1550
|
@GeneralUtilities.check_arguments
|
1553
|
-
def run_program_with_retry(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, print_live_output: bool = False,amount_of_attempts:int=5) -> tuple[int, str, str, int]:
|
1554
|
-
return GeneralUtilities.retry_action(lambda: self.run_program(program, 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,print_live_output), amount_of_attempts)
|
1551
|
+
def run_program_with_retry(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, print_live_output: bool = False, amount_of_attempts: int = 5) -> tuple[int, str, str, int]:
|
1552
|
+
return GeneralUtilities.retry_action(lambda: self.run_program(program, 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, print_live_output), amount_of_attempts)
|
1555
1553
|
|
1556
1554
|
# Return-values program_runner: Exitcode, StdOut, StdErr, Pid
|
1557
1555
|
@GeneralUtilities.check_arguments
|
@@ -1851,50 +1849,47 @@ DNS = {domain}
|
|
1851
1849
|
folder = os.path.dirname(csproj_file)
|
1852
1850
|
csproj_filename = os.path.basename(csproj_file)
|
1853
1851
|
GeneralUtilities.write_message_to_stdout(f"Check for updates in {csproj_filename}")
|
1854
|
-
result = self.run_program_with_retry("dotnet", f"list {csproj_filename} package --outdated", folder,print_errors_as_information=True)
|
1852
|
+
result = self.run_program_with_retry("dotnet", f"list {csproj_filename} package --outdated", folder, print_errors_as_information=True)
|
1855
1853
|
for line in result[1].replace("\r", "").split("\n"):
|
1856
1854
|
# Relevant output-lines are something like " > NJsonSchema 10.7.0 10.7.0 10.9.0"
|
1857
1855
|
if ">" in line:
|
1858
1856
|
package_name = line.replace(">", "").strip().split(" ")[0]
|
1859
1857
|
if not (package_name in ignored_dependencies):
|
1860
1858
|
GeneralUtilities.write_message_to_stdout(f"Update package {package_name}...")
|
1861
|
-
self.run_program("dotnet", f"add {csproj_filename} package {package_name}", folder,print_errors_as_information=True)
|
1862
|
-
|
1859
|
+
self.run_program("dotnet", f"add {csproj_filename} package {package_name}", folder, print_errors_as_information=True)
|
1863
1860
|
|
1864
1861
|
@GeneralUtilities.check_arguments
|
1865
|
-
def dotnet_package_is_available(self,package_name:str,package_version:str,source:str):
|
1866
|
-
default_source_address="nuget.org"
|
1867
|
-
if source==default_source_address:
|
1862
|
+
def dotnet_package_is_available(self, package_name: str, package_version: str, source: str):
|
1863
|
+
default_source_address = "nuget.org"
|
1864
|
+
if source == default_source_address:
|
1868
1865
|
GeneralUtilities.write_message_to_stdout(f"Wait until package {package_name} v{package_version} is available on {source}.")
|
1869
1866
|
headers = {'Cache-Control': 'no-cache'}
|
1870
|
-
r=requests.get(f"https://api.{default_source_address}/v3-flatcontainer/{package_name.lower()}/{package_version}/{package_name.lower()}.nuspec", timeout=5,headers=headers)
|
1871
|
-
return r.status_code==200
|
1867
|
+
r = requests.get(f"https://api.{default_source_address}/v3-flatcontainer/{package_name.lower()}/{package_version}/{package_name.lower()}.nuspec", timeout=5, headers=headers)
|
1868
|
+
return r.status_code == 200
|
1872
1869
|
else:
|
1873
1870
|
raise ValueError(f"dotnet_package_is_available is not implemented yet for other sources than {default_source_address}.")
|
1874
1871
|
|
1875
1872
|
@GeneralUtilities.check_arguments
|
1876
|
-
def wait_until_dotnet_package_is_available(self,package_name:str,package_version:str,source:str):
|
1877
|
-
while not self.dotnet_package_is_available(package_name,package_version,source):
|
1873
|
+
def wait_until_dotnet_package_is_available(self, package_name: str, package_version: str, source: str):
|
1874
|
+
while not self.dotnet_package_is_available(package_name, package_version, source):
|
1878
1875
|
time.sleep(5)
|
1879
1876
|
|
1880
|
-
|
1881
1877
|
@GeneralUtilities.check_arguments
|
1882
|
-
def python_package_is_available(self,package_name:str,package_version:str,source:str):
|
1883
|
-
default_source_address="pypi.org"
|
1884
|
-
if source==default_source_address:
|
1878
|
+
def python_package_is_available(self, package_name: str, package_version: str, source: str):
|
1879
|
+
default_source_address = "pypi.org"
|
1880
|
+
if source == default_source_address:
|
1885
1881
|
GeneralUtilities.write_message_to_stdout(f"Wait until package {package_name} v{package_version} is available on {source}.")
|
1886
1882
|
headers = {'Cache-Control': 'no-cache'}
|
1887
|
-
r=requests.get(f"https://{default_source_address}/pypi/{package_name}/{package_version}/json", timeout=5,headers=headers)
|
1888
|
-
return r.status_code==200
|
1883
|
+
r = requests.get(f"https://{default_source_address}/pypi/{package_name}/{package_version}/json", timeout=5, headers=headers)
|
1884
|
+
return r.status_code == 200
|
1889
1885
|
else:
|
1890
1886
|
raise ValueError(f"python_package_is_available is not implemented yet for other sources than {default_source_address}.")
|
1891
1887
|
|
1892
1888
|
@GeneralUtilities.check_arguments
|
1893
|
-
def wait_until_python_package_is_available(self,package_name:str,package_version:str,source:str):
|
1894
|
-
while not self.python_package_is_available(package_name,package_version,source):
|
1889
|
+
def wait_until_python_package_is_available(self, package_name: str, package_version: str, source: str):
|
1890
|
+
while not self.python_package_is_available(package_name, package_version, source):
|
1895
1891
|
time.sleep(5)
|
1896
1892
|
|
1897
|
-
|
1898
1893
|
@GeneralUtilities.check_arguments
|
1899
1894
|
def create_deb_package(self, toolname: str, binary_folder: str, control_file_content: str, deb_output_folder: str, verbosity: int, permission_of_executable_file_as_octet_triple: int) -> None:
|
1900
1895
|
|
@@ -1018,7 +1018,7 @@ class TasksForCommonProjectStructure:
|
|
1018
1018
|
target_folder_base = os.path.join(information.artifacts_folder, information.projectname, project_version)
|
1019
1019
|
GeneralUtilities.ensure_directory_exists(target_folder_base)
|
1020
1020
|
|
1021
|
-
self.build_codeunits(information.repository, information.verbosity, information.target_environmenttype_for_productive, information.additional_arguments_file, False, information.export_target, [], True, "Generate artifacts")# Generate artifacts after merge (because now are constants like commit-id of the new version available)
|
1021
|
+
self.build_codeunits(information.repository, information.verbosity, information.target_environmenttype_for_productive, information.additional_arguments_file, False, information.export_target, [], True, "Generate artifacts") # Generate artifacts after merge (because now are constants like commit-id of the new version available)
|
1022
1022
|
|
1023
1023
|
reference_folder = os.path.join(information.reference_repository, "ReferenceContent")
|
1024
1024
|
|
@@ -1252,7 +1252,7 @@ class TasksForCommonProjectStructure:
|
|
1252
1252
|
|
1253
1253
|
self.__sc.git_checkout(repository_folder, source_branch)
|
1254
1254
|
self.build_codeunits(repository_folder, verbosity, TasksForCommonProjectStructure.get_qualitycheck_environment_name(), additional_arguments_file, True, None, [], True, "Check if product is buildable")
|
1255
|
-
self.__sc.git_merge(repository_folder, source_branch, target_branch, False, False, None)
|
1255
|
+
self.__sc.git_merge(repository_folder, source_branch, target_branch, False, False, None, False, False)
|
1256
1256
|
self.__sc.git_commit(repository_folder, f'Merge branch {source_branch} into {target_branch}', stage_all_changes=True, no_changes_behavior=1)
|
1257
1257
|
self.__sc.git_checkout(repository_folder, target_branch)
|
1258
1258
|
if fast_forward_source_branch:
|
@@ -1300,8 +1300,8 @@ class TasksForCommonProjectStructure:
|
|
1300
1300
|
# hint: arguments can be overwritten by commandline_arguments
|
1301
1301
|
folder_of_this_file = os.path.dirname(create_release_file)
|
1302
1302
|
verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
|
1303
|
-
result=self.__sc.run_program("python", f"CreateRelease.py --overwrite_verbosity {str(verbosity)}", folder_of_this_file, verbosity=verbosity, log_file=logfile, addLogOverhead=addLogOverhead,print_live_output=True,throw_exception_if_exitcode_is_not_zero=False)
|
1304
|
-
if result[0]!=0:
|
1303
|
+
result = self.__sc.run_program("python", f"CreateRelease.py --overwrite_verbosity {str(verbosity)}", folder_of_this_file, verbosity=verbosity, log_file=logfile, addLogOverhead=addLogOverhead, print_live_output=True, throw_exception_if_exitcode_is_not_zero=False)
|
1304
|
+
if result[0] != 0:
|
1305
1305
|
raise ValueError(f"CreateRelease.py resulted in exitcode {result[0]}.")
|
1306
1306
|
|
1307
1307
|
@GeneralUtilities.check_arguments
|
@@ -1315,7 +1315,7 @@ class TasksForCommonProjectStructure:
|
|
1315
1315
|
self.__sc.run_program("git", "clean -dfx", information.repository, verbosity=information.verbosity, throw_exception_if_exitcode_is_not_zero=True)
|
1316
1316
|
project_version = self.__sc.get_semver_version_from_gitversion(information.repository)
|
1317
1317
|
|
1318
|
-
self.build_codeunits(information.repository, information.verbosity, information.target_environmenttype_for_qualitycheck, information.additional_arguments_file, False, information.export_target, [], True, "Productive build")#verify hat codeunits are buildable with productive-config before merge
|
1318
|
+
self.build_codeunits(information.repository, information.verbosity, information.target_environmenttype_for_qualitycheck, information.additional_arguments_file, False, information.export_target, [], True, "Productive build") # verify hat codeunits are buildable with productive-config before merge
|
1319
1319
|
|
1320
1320
|
self.assert_no_uncommitted_changes(information.repository)
|
1321
1321
|
|
@@ -2445,11 +2445,11 @@ class TasksForCommonProjectStructure:
|
|
2445
2445
|
self.__sc.assert_is_git_repository(repository_folder)
|
2446
2446
|
repository_folder = GeneralUtilities.resolve_relative_path_from_current_working_directory(repository_folder)
|
2447
2447
|
codeunits = self.get_codeunits(repository_folder, False)
|
2448
|
-
self.build_specific_codeunits(repository_folder, codeunits, verbosity, target_environmenttype, additional_arguments_file, is_pre_merge, export_target_directory, False, commandline_arguments, do_git_clean_when_no_changes,note)
|
2448
|
+
self.build_specific_codeunits(repository_folder, codeunits, verbosity, target_environmenttype, additional_arguments_file, is_pre_merge, export_target_directory, False, commandline_arguments, do_git_clean_when_no_changes, note)
|
2449
2449
|
|
2450
2450
|
@GeneralUtilities.check_arguments
|
2451
2451
|
def build_specific_codeunits(self, repository_folder: str, codeunits: list[str], verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None, is_pre_merge: bool = False, export_target_directory: str = None, assume_dependent_codeunits_are_already_built: bool = True, commandline_arguments: list[str] = [], do_git_clean_when_no_changes: bool = False, note: str = None) -> None:
|
2452
|
-
if verbosity>2:
|
2452
|
+
if verbosity > 2:
|
2453
2453
|
GeneralUtilities.write_message_to_stdout(f"Start building codeunits for repository '{repository_folder}'...")
|
2454
2454
|
self.__sc.assert_is_git_repository(repository_folder)
|
2455
2455
|
self.__check_target_environmenttype(target_environmenttype)
|
@@ -2470,8 +2470,8 @@ class TasksForCommonProjectStructure:
|
|
2470
2470
|
prepare_build_codeunits_scripts = os.path.join(project_resources_folder, PrepareBuildCodeunits_script_name)
|
2471
2471
|
if os.path.isfile(prepare_build_codeunits_scripts):
|
2472
2472
|
GeneralUtilities.write_message_to_stdout(f'Run "{PrepareBuildCodeunits_script_name}"')
|
2473
|
-
result=self.__sc.run_program("python", f"{PrepareBuildCodeunits_script_name}", project_resources_folder,throw_exception_if_exitcode_is_not_zero=False, print_live_output=True)
|
2474
|
-
if result[0]!=0:
|
2473
|
+
result = self.__sc.run_program("python", f"{PrepareBuildCodeunits_script_name}", project_resources_folder, throw_exception_if_exitcode_is_not_zero=False, print_live_output=True)
|
2474
|
+
if result[0] != 0:
|
2475
2475
|
raise ValueError(f"PrepareBuildCodeunits.py resulted in exitcode {result[0]}.")
|
2476
2476
|
|
2477
2477
|
for subfolder in subfolders:
|
@@ -2903,7 +2903,7 @@ class TasksForCommonProjectStructure:
|
|
2903
2903
|
# update dependencies of resources
|
2904
2904
|
global_scripts_folder = os.path.join(repository_folder, "Other", "Scripts")
|
2905
2905
|
if os.path.isfile(os.path.join(global_scripts_folder, update_dependencies_script_filename)):
|
2906
|
-
self.__sc.run_program("python", update_dependencies_script_filename, global_scripts_folder,print_live_output=True)
|
2906
|
+
self.__sc.run_program("python", update_dependencies_script_filename, global_scripts_folder, print_live_output=True)
|
2907
2907
|
|
2908
2908
|
# update dependencies of codeunits
|
2909
2909
|
for codeunit in codeunits:
|
@@ -2913,7 +2913,7 @@ class TasksForCommonProjectStructure:
|
|
2913
2913
|
codeunit_folder = os.path.join(repository_folder, codeunit)
|
2914
2914
|
update_dependencies_script_folder = os.path.join(codeunit_folder, "Other")
|
2915
2915
|
GeneralUtilities.ensure_directory_exists(os.path.join(update_dependencies_script_folder, "Resources", "CodeAnalysisResult"))
|
2916
|
-
self.__sc.run_program("python", update_dependencies_script_filename, update_dependencies_script_folder, verbosity,print_live_output=True)
|
2916
|
+
self.__sc.run_program("python", update_dependencies_script_filename, update_dependencies_script_folder, verbosity, print_live_output=True)
|
2917
2917
|
if self.__sc.git_repository_has_uncommitted_changes(repository_folder):
|
2918
2918
|
version_of_project = self.get_version_of_project(repository_folder)
|
2919
2919
|
changelog_file = os.path.join(repository_folder, "Other", "Resources", "Changelog", f"v{version_of_project}.md")
|
@@ -2961,9 +2961,13 @@ class TasksForCommonProjectStructure:
|
|
2961
2961
|
# prepare
|
2962
2962
|
self.assert_no_uncommitted_changes(repository_folder)
|
2963
2963
|
self.assert_no_uncommitted_changes(reference_folder)
|
2964
|
-
self.
|
2964
|
+
self.assert_no_uncommitted_changes(build_repository_folder)
|
2965
|
+
self.__sc.git_checkout(repository_folder, merge_source_branch, True)
|
2966
|
+
self.__sc.git_checkout(reference_folder, "main", True)
|
2967
|
+
self.__sc.git_checkout(build_repository_folder, "main", True)
|
2965
2968
|
self.assert_no_uncommitted_changes(repository_folder)
|
2966
2969
|
self.assert_no_uncommitted_changes(reference_folder)
|
2970
|
+
self.__sc.git_commit(build_repository_folder, "Updated submodules")
|
2967
2971
|
|
2968
2972
|
if "--dependencyupdate" in generic_prepare_new_release_arguments.commandline_arguments:
|
2969
2973
|
self.generic_update_dependencies(repository_folder)
|
@@ -2985,7 +2989,6 @@ class TasksForCommonProjectStructure:
|
|
2985
2989
|
self.__sc.git_commit(build_repository_folder, "Updated submodule due to merge to main-branch.")
|
2986
2990
|
GeneralUtilities.write_message_to_stdout(f"Finished prepare release for {generic_prepare_new_release_arguments.product_name}.")
|
2987
2991
|
|
2988
|
-
|
2989
2992
|
class GenericCreateReleaseArguments():
|
2990
2993
|
current_file: str
|
2991
2994
|
product_name: str
|
@@ -3025,6 +3028,7 @@ class TasksForCommonProjectStructure:
|
|
3025
3028
|
self.__sc.git_checkout(repository_folder, merge_source_branch)
|
3026
3029
|
reference_repo: str = os.path.join(build_repository_folder, "Submodules", f"{generic_create_release_arguments.product_name}Reference")
|
3027
3030
|
self.__sc.git_commit(reference_repo, "Updated reference")
|
3031
|
+
self.__sc.git_push_with_retry(reference_repo, generic_create_release_arguments.common_remote_name, "main", "main")
|
3028
3032
|
self.__sc.git_commit(build_repository_folder, "Updated submodule")
|
3029
3033
|
|
3030
3034
|
# create release
|
@@ -3051,8 +3055,11 @@ class TasksForCommonProjectStructure:
|
|
3051
3055
|
self.main_branch_name = "main"
|
3052
3056
|
|
3053
3057
|
@GeneralUtilities.check_arguments
|
3054
|
-
def create_changelog_entry(self, repositoryfolder: str, message: str, commit: bool):
|
3058
|
+
def create_changelog_entry(self, repositoryfolder: str, message: str, commit: bool, force: bool):
|
3055
3059
|
self.__sc.assert_is_git_repository(repositoryfolder)
|
3060
|
+
random_file = os.path.join(repositoryfolder, str(uuid.uuid4()))
|
3061
|
+
if force and not self.__sc.git_repository_has_uncommitted_changes(repositoryfolder):
|
3062
|
+
GeneralUtilities.ensure_file_exists(random_file)
|
3056
3063
|
current_version = self.get_version_of_project(repositoryfolder)
|
3057
3064
|
changelog_file = os.path.join(repositoryfolder, "Other", "Resources", "Changelog", f"v{current_version}.md")
|
3058
3065
|
if os.path.isdir(changelog_file):
|
@@ -3065,6 +3072,9 @@ class TasksForCommonProjectStructure:
|
|
3065
3072
|
|
3066
3073
|
- {message}
|
3067
3074
|
""")
|
3075
|
+
GeneralUtilities.ensure_file_does_not_exist(random_file)
|
3076
|
+
if commit:
|
3077
|
+
self.__sc.git_commit(repositoryfolder, f"Added changelog-file for v{current_version}.")
|
3068
3078
|
|
3069
3079
|
@GeneralUtilities.check_arguments
|
3070
3080
|
def update_http_documentation(self, update_http_documentation_arguments: UpdateHTTPDocumentationArguments):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: ScriptCollection
|
3
|
-
Version: 3.5.
|
3
|
+
Version: 3.5.86
|
4
4
|
Summary: The ScriptCollection is the place for reusable scripts.
|
5
5
|
Home-page: https://github.com/anionDev/ScriptCollection
|
6
6
|
Author: Marius Göcke
|
@@ -24,7 +24,7 @@ Requires-Python: >=3.10
|
|
24
24
|
Description-Content-Type: text/markdown
|
25
25
|
Requires-Dist: build>=1.2.2.post1
|
26
26
|
Requires-Dist: coverage>=7.6.12
|
27
|
-
Requires-Dist: cyclonedx-bom>=5.
|
27
|
+
Requires-Dist: cyclonedx-bom>=5.3.0
|
28
28
|
Requires-Dist: defusedxml>=0.7.1
|
29
29
|
Requires-Dist: keyboard>=0.13.5
|
30
30
|
Requires-Dist: lcov-cobertura>=2.1.1
|
@@ -1,16 +1,16 @@
|
|
1
|
-
ScriptCollection/Executables.py,sha256=
|
1
|
+
ScriptCollection/Executables.py,sha256=XwnhziKm3HdsJNkvj2TCTf-KS2e4RKibpNcNTZOHFJ4,30175
|
2
2
|
ScriptCollection/GeneralUtilities.py,sha256=VVbbGFD4qLwWV211-E-n3faP2fZGc8mOBlKLd0oKHl4,40765
|
3
3
|
ScriptCollection/ProcessesRunner.py,sha256=3mu4ZxzZleQo0Op6o9EYTCFiJfb6kx5ov2YfZfT89mU,1395
|
4
4
|
ScriptCollection/ProgramRunnerBase.py,sha256=2kMIAqdc65UjBAddOZkzy_aFx9h5roZ5a4bQNM6RV6Y,2480
|
5
5
|
ScriptCollection/ProgramRunnerEpew.py,sha256=4pjEd0r9Fcz3TTDv0MdTSd5KkigYXcWUVI1X43regfU,6477
|
6
6
|
ScriptCollection/ProgramRunnerPopen.py,sha256=BPY7-ZMIlqT7JOKz8qlB5c0laF2Js-ijzqk09GxZC48,3821
|
7
7
|
ScriptCollection/RPStream.py,sha256=NRRHL3YSP3D9MuAV2jB_--0KUKCsvJGxeKnxgrRZ9kY,1545
|
8
|
-
ScriptCollection/ScriptCollectionCore.py,sha256=
|
9
|
-
ScriptCollection/TasksForCommonProjectStructure.py,sha256=
|
8
|
+
ScriptCollection/ScriptCollectionCore.py,sha256=QsyoePkvnrP1DpEy0V5wiOHewiim649hlPR0uQN5fJw,123286
|
9
|
+
ScriptCollection/TasksForCommonProjectStructure.py,sha256=0G2onG2crhkn3ivRqfVtHcg9WgwRXT488X0zEy8CSe4,216807
|
10
10
|
ScriptCollection/UpdateCertificates.py,sha256=Eynbgu7k9jLxApP2D_8Il77B6BFjJap6K7oTeEAZYbk,7790
|
11
11
|
ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
scriptcollection-3.5.86.dist-info/METADATA,sha256=JSg4iWzozzhdD_I0svPAbfBywMaZYuum13ycscoCcdk,7664
|
13
|
+
scriptcollection-3.5.86.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
14
|
+
scriptcollection-3.5.86.dist-info/entry_points.txt,sha256=1jAL5AuB8mvdw2v-6E7wCZFThurQxchiQynL8DCi-Yg,3545
|
15
|
+
scriptcollection-3.5.86.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
|
16
|
+
scriptcollection-3.5.86.dist-info/RECORD,,
|
File without changes
|
File without changes
|