ScriptCollection 3.4.55__py3-none-any.whl → 3.5.44__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.
@@ -12,6 +12,8 @@ import secrets
12
12
  import string as strin
13
13
  import sys
14
14
  import traceback
15
+ import warnings
16
+ import functools
15
17
  from datetime import datetime, timedelta, date
16
18
  from os import listdir
17
19
  from os.path import isfile, join, isdir
@@ -49,19 +51,27 @@ class GeneralUtilities:
49
51
  # Check type of arguments if the type is a generic type seems to be impossible.
50
52
  if not GeneralUtilities.is_generic(function.__annotations__[parameters[index]]):
51
53
  if not isinstance(argument, function.__annotations__[parameters[index]]):
52
- raise TypeError(f"Argument with index {index} for function {function.__name__} ('{str(argument)}') is not of type " +
53
- f"{ function.__annotations__[parameters[index]]} but has type "+str(type(argument)))
54
+ raise TypeError(f"Argument with index {index} for function {function.__name__} ('{str(argument)}') is not of type {function.__annotations__[parameters[index]]} but has type "+str(type(argument)))
54
55
  for index, named_argument in enumerate(named_args):
55
56
  if named_args[named_argument] is not None:
56
57
  if parameters[index] in function.__annotations__:
57
58
  if not GeneralUtilities.is_generic(function.__annotations__.get(named_argument)):
58
59
  if not isinstance(named_args[named_argument], function.__annotations__.get(named_argument)):
59
- raise TypeError(f"Argument with name {named_argument} for function {function.__name__} ('{str(named_args[named_argument])}') " +
60
- f"is not of type { function.__annotations__.get(named_argument)}")
60
+ raise TypeError(f"Argument with name {named_argument} for function {function.__name__} ('{str(named_args[named_argument])}') is not of type {function.__annotations__.get(named_argument)}")
61
61
  return function(*args, **named_args)
62
62
  __check_function.__doc__ = function.__doc__
63
63
  return __check_function
64
64
 
65
+ @staticmethod
66
+ def deprecated(func):
67
+ @functools.wraps(func)
68
+ def new_func(*args, **kwargs):
69
+ warnings.simplefilter('always', DeprecationWarning)
70
+ warnings.warn(f"Call to deprecated function {func.__name__}", category=DeprecationWarning, stacklevel=2)
71
+ warnings.simplefilter('default', DeprecationWarning)
72
+ return func(*args, **kwargs)
73
+ return new_func
74
+
65
75
  @staticmethod
66
76
  @check_arguments
67
77
  def args_array_surround_with_quotes_if_required(arguments: list[str]) -> list[str]:
@@ -381,8 +391,8 @@ class GeneralUtilities:
381
391
 
382
392
  @staticmethod
383
393
  @check_arguments
384
- def rmtree(directory: str) -> None:
385
- shutil.rmtree(directory, onerror=GeneralUtilities.__remove_readonly)
394
+ def __rmtree(directory: str) -> None:
395
+ shutil.rmtree(directory, onerror=GeneralUtilities.__remove_readonly) # pylint: disable=deprecated-argument
386
396
 
387
397
  @staticmethod
388
398
  @check_arguments
@@ -394,8 +404,8 @@ class GeneralUtilities:
394
404
  os.chmod(filename, stat.S_IWUSR)
395
405
  os.remove(filename)
396
406
  for name in dirs:
397
- GeneralUtilities.rmtree(os.path.join(root, name))
398
- GeneralUtilities.rmtree(path)
407
+ GeneralUtilities.__rmtree(os.path.join(root, name))
408
+ GeneralUtilities.__rmtree(path)
399
409
 
400
410
  @staticmethod
401
411
  @check_arguments
@@ -461,6 +471,16 @@ class GeneralUtilities:
461
471
  result.append(fileB)
462
472
  return result
463
473
 
474
+ @staticmethod
475
+ @check_arguments
476
+ def to_pascal_case(s: str) -> str:
477
+ return ''.join(current.lower() if prev.isalnum() else current.upper() for prev, current in zip(' ' + s, s) if current.isalnum())
478
+
479
+ @staticmethod
480
+ @check_arguments
481
+ def find_between(s: str, start: str, end: str) -> str:
482
+ return s.split(start)[1].split(end)[0]
483
+
464
484
  @staticmethod
465
485
  @check_arguments
466
486
  def write_lines_to_file(file: str, lines: list, encoding="utf-8") -> None:
@@ -545,6 +565,12 @@ class GeneralUtilities:
545
565
  except AttributeError:
546
566
  return ctypes.windll.shell32.IsUserAnAdmin() == 1
547
567
 
568
+ @staticmethod
569
+ @check_arguments
570
+ def ensure_elevated_privileges() -> None:
571
+ if (not GeneralUtilities.current_user_has_elevated_privileges()):
572
+ raise ValueError("Not enough privileges.")
573
+
548
574
  @staticmethod
549
575
  @check_arguments
550
576
  def rename_names_of_all_files_and_folders(folder: str, replace_from: str, replace_to: str, replace_only_full_match=False):
@@ -558,12 +584,14 @@ class GeneralUtilities:
558
584
  @check_arguments
559
585
  def get_direct_files_of_folder(folder: str) -> list[str]:
560
586
  result = [os.path.join(folder, f) for f in listdir(folder) if isfile(join(folder, f))]
587
+ result = sorted(result, key=str.casefold)
561
588
  return result
562
589
 
563
590
  @staticmethod
564
591
  @check_arguments
565
592
  def get_direct_folders_of_folder(folder: str) -> list[str]:
566
593
  result = [os.path.join(folder, f) for f in listdir(folder) if isdir(join(folder, f))]
594
+ result = sorted(result, key=str.casefold)
567
595
  return result
568
596
 
569
597
  @staticmethod
@@ -573,6 +601,7 @@ class GeneralUtilities:
573
601
  result.extend(GeneralUtilities.get_direct_files_of_folder(folder))
574
602
  for subfolder in GeneralUtilities.get_direct_folders_of_folder(folder):
575
603
  result.extend(GeneralUtilities.get_all_files_of_folder(subfolder))
604
+ result = sorted(result, key=str.casefold)
576
605
  return result
577
606
 
578
607
  @staticmethod
@@ -583,12 +612,13 @@ class GeneralUtilities:
583
612
  result.extend(subfolders)
584
613
  for subfolder in subfolders:
585
614
  result.extend(GeneralUtilities.get_all_folders_of_folder(subfolder))
615
+ result = sorted(result, key=str.casefold)
586
616
  return result
587
617
 
588
618
  @staticmethod
589
619
  @check_arguments
590
620
  def get_all_objects_of_folder(folder: str) -> list[str]:
591
- return GeneralUtilities.get_all_files_of_folder(folder) + GeneralUtilities.get_all_folders_of_folder(folder)
621
+ return sorted(GeneralUtilities.get_all_files_of_folder(folder) + GeneralUtilities.get_all_folders_of_folder(folder), key=str.casefold)
592
622
 
593
623
  @staticmethod
594
624
  @check_arguments
@@ -718,8 +748,7 @@ class GeneralUtilities:
718
748
 
719
749
  @staticmethod
720
750
  @check_arguments
721
- def read_csv_file(file: str, ignore_first_line: bool = False, treat_number_sign_at_begin_of_line_as_comment: bool = True, trim_values: bool = True,
722
- encoding="utf-8", ignore_empty_lines: bool = True, separator_character: str = ";", values_are_surrounded_by_quotes: bool = False) -> list[list[str]]:
751
+ def read_csv_file(file: str, ignore_first_line: bool = False, treat_number_sign_at_begin_of_line_as_comment: bool = True, trim_values: bool = True, encoding="utf-8", ignore_empty_lines: bool = True, separator_character: str = ";", values_are_surrounded_by_quotes: bool = False) -> list[list[str]]:
723
752
  lines = GeneralUtilities.read_lines_from_file(file, encoding)
724
753
 
725
754
  if ignore_first_line:
@@ -768,10 +797,9 @@ class GeneralUtilities:
768
797
 
769
798
  @staticmethod
770
799
  @check_arguments
800
+ @deprecated
771
801
  def absolute_file_paths(directory: str) -> list[str]:
772
- for dirpath, _, filenames in os.walk(directory):
773
- for filename in filenames:
774
- yield os.path.abspath(os.path.join(dirpath, filename))
802
+ return GeneralUtilities.get_all_files_of_folder(directory)
775
803
 
776
804
  @staticmethod
777
805
  @check_arguments
@@ -852,3 +880,12 @@ class GeneralUtilities:
852
880
  @check_arguments
853
881
  def replace_variable_in_string(input_string: str, variable_name: str, variable_value: str) -> None:
854
882
  return input_string.replace(f"__[{variable_name}]__", variable_value)
883
+
884
+ @staticmethod
885
+ @check_arguments
886
+ def input(prompt: str, print_result: bool) -> str: # This function is a workaround for usescases like python scripts which calls input(...) using epew because then the prompt is not printed by the built-in-input-function.
887
+ GeneralUtilities.write_message_to_stdout(prompt)
888
+ result: str = input()
889
+ if print_result:
890
+ GeneralUtilities.write_message_to_stdout(f"Result: {result}")
891
+ return result
@@ -0,0 +1,41 @@
1
+ import psutil
2
+ from .ScriptCollectionCore import ScriptCollectionCore
3
+
4
+ # runs multiple processes in parallel and terminate all if at least one is terminated
5
+
6
+
7
+ class ProcessStartInformation:
8
+ workingdirectory: str = None
9
+ program: str = None
10
+ arguments: str = None
11
+
12
+ def __init__(self, workingdirectory: str, program: str, arguments: str):
13
+ self.workingdirectory = workingdirectory
14
+ self.program = program
15
+ self.arguments = arguments
16
+
17
+
18
+ class ProcessesRunner:
19
+ sc: ScriptCollectionCore
20
+ processes: list[ProcessStartInformation]
21
+
22
+ def __init__(self, processes: list[ProcessStartInformation]):
23
+ self.sc = ScriptCollectionCore()
24
+ self.processes = processes
25
+
26
+ def run(self):
27
+ pids: list[int] = list[int]()
28
+ for processstartinfo in self.processes:
29
+ pids.append(self.sc.run_program_async(processstartinfo.program, processstartinfo.argumentss, processstartinfo.workingdirectory))
30
+ enabled = True
31
+ while enabled:
32
+ for pid in pids:
33
+ if not psutil.pid_exists(pid):
34
+ enabled = False
35
+ # one program terminate so exit and terminate all now
36
+ processes = psutil.process_iter()
37
+ for pid in pids:
38
+ if psutil.pid_exists(pid):
39
+ for proc in processes:
40
+ if proc.pid == pid:
41
+ proc.kill()
@@ -1,42 +1,47 @@
1
- from abc import abstractmethod
2
- from subprocess import Popen
3
- from .GeneralUtilities import GeneralUtilities
4
-
5
-
6
- class ProgramRunnerBase:
7
-
8
- # Return-values program_runner: Pid
9
- @abstractmethod
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) -> Popen:
12
- raise NotImplementedError
13
-
14
- # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
15
- @abstractmethod
16
- @GeneralUtilities.check_arguments
17
- def wait(self, process: Popen, custom_argument: object) -> tuple[int, str, str, int]:
18
- raise NotImplementedError
19
-
20
- # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
21
- @abstractmethod
22
- @GeneralUtilities.check_arguments
23
- def run_program_argsasarray(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None) -> tuple[int, str, str, int]:
24
- raise NotImplementedError
25
-
26
- # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
27
- @abstractmethod
28
- @GeneralUtilities.check_arguments
29
- def run_program(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None) -> tuple[int, str, str, int]:
30
- raise NotImplementedError
31
-
32
- # Return-values program_runner: Pid
33
- @abstractmethod
34
- @GeneralUtilities.check_arguments
35
- def run_program_argsasarray_async(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None) -> int:
36
- raise NotImplementedError
37
-
38
- # Return-values program_runner: Pid
39
- @abstractmethod
40
- @GeneralUtilities.check_arguments
41
- def run_program_async(self, program: str, arguments: str, working_directory: str, custom_argument: object) -> int:
42
- raise NotImplementedError
1
+ from abc import abstractmethod
2
+ from subprocess import Popen
3
+ from .GeneralUtilities import GeneralUtilities
4
+
5
+
6
+ class ProgramRunnerBase:
7
+
8
+ # Return-values program_runner: Pid
9
+ @abstractmethod
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:
12
+ # Verbosity:
13
+ # 0=Quiet (No output will be printed.)
14
+ # 1=Normal (If the exitcode of the executed program is not 0 then the StdErr will be printed.)
15
+ # 2=Full (Prints StdOut and StdErr of the executed program.)
16
+ # 3=Verbose (Same as "Full" but with some more information.)
17
+ raise NotImplementedError
18
+
19
+ # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
20
+ @abstractmethod
21
+ @GeneralUtilities.check_arguments
22
+ def wait(self, process: Popen, custom_argument: object) -> tuple[int, str, str, int]:
23
+ raise NotImplementedError
24
+
25
+ # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
26
+ @abstractmethod
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]:
29
+ raise NotImplementedError
30
+
31
+ # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
32
+ @abstractmethod
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]:
35
+ raise NotImplementedError
36
+
37
+ # Return-values program_runner: Pid
38
+ @abstractmethod
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:
41
+ raise NotImplementedError
42
+
43
+ # Return-values program_runner: Pid
44
+ @abstractmethod
45
+ @GeneralUtilities.check_arguments
46
+ def run_program_async(self, program: str, arguments: str, working_directory: str, custom_argument: object, interactive:bool=False) -> int:
47
+ raise NotImplementedError
@@ -1,122 +1,122 @@
1
- import os
2
- import base64
3
- import tempfile
4
- from subprocess import Popen
5
- from uuid import uuid4
6
-
7
- from .GeneralUtilities import GeneralUtilities
8
- from .ProgramRunnerBase import ProgramRunnerBase
9
- from .ProgramRunnerPopen import ProgramRunnerPopen
10
-
11
-
12
- class CustomEpewArgument:
13
-
14
- print_errors_as_information: bool
15
- log_file: str
16
- timeoutInSeconds: int
17
- addLogOverhead: bool
18
- title: str
19
- log_namespace: str
20
- verbosity: int
21
- arguments_for_log: list[str]
22
- tempdir = os.path.join(tempfile.gettempdir(), str(uuid4()))
23
- stdoutfile = tempdir + ".epew.stdout.txt"
24
- stderrfile = tempdir + ".epew.stderr.txt"
25
- exitcodefile = tempdir + ".epew.exitcode.txt"
26
- pidfile = tempdir + ".epew.pid.txt"
27
-
28
- def __init__(self, print_errors_as_information: bool, log_file: str, timeoutInSeconds: int, addLogOverhead: bool, title: str, log_namespace: str, verbosity: int, arguments_for_log: list[str]):
29
- self.print_errors_as_information = print_errors_as_information
30
- self.log_file = log_file
31
- self.timeoutInSeconds = timeoutInSeconds
32
- self.addLogOverhead = addLogOverhead
33
- self.title = title
34
- self.log_namespace = log_namespace
35
- self.verbosity = verbosity
36
- self.arguments_for_log = arguments_for_log
37
-
38
-
39
- class ProgramRunnerEpew(ProgramRunnerBase):
40
-
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) -> Popen:
43
- if GeneralUtilities.epew_is_available():
44
- custom_argument: CustomEpewArgument = custom_argument
45
- args = []
46
-
47
- base64argument = base64.b64encode(' '.join(arguments_as_array).encode('utf-8')).decode('utf-8')
48
- args.append(f'-p "{program}"')
49
- args.append(f'-a {base64argument}')
50
- args.append('-b')
51
- args.append(f'-w "{working_directory}"')
52
- if custom_argument.stdoutfile is not None:
53
- args.append(f'-o {custom_argument.stdoutfile}')
54
- if custom_argument.stderrfile is not None:
55
- args.append(f'-e {custom_argument.stderrfile}')
56
- if custom_argument.exitcodefile is not None:
57
- args.append(f'-x {custom_argument.exitcodefile}')
58
- if custom_argument.pidfile is not None:
59
- args.append(f'-r {custom_argument.pidfile}')
60
- args.append(f'-d {str(custom_argument.timeoutInSeconds*1000)}')
61
- args.append(f'-t "{custom_argument.title}"')
62
- args.append(f'-l "{custom_argument.log_namespace}"')
63
- if not GeneralUtilities.string_is_none_or_whitespace(custom_argument.log_file):
64
- args.append(f'-f "{custom_argument.log_file}"')
65
- if custom_argument.print_errors_as_information:
66
- args.append("-i")
67
- if custom_argument.addLogOverhead:
68
- args.append("-g")
69
- args.append("-v "+str(custom_argument.verbosity))
70
- return ProgramRunnerPopen().run_program_argsasarray_async_helper("epew", args, working_directory)
71
- else:
72
- raise ValueError("Epew is not available.")
73
-
74
- # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
75
- @GeneralUtilities.check_arguments
76
- def wait(self, process: Popen, custom_argument: object = None) -> tuple[int, str, str, int]:
77
- process.wait()
78
- custom_argument: CustomEpewArgument = custom_argument
79
- stdout = self.__load_text(custom_argument.output_file_for_stdout)
80
- stderr = self.__load_text(custom_argument.output_file_for_stderr)
81
- exit_code = self.__get_number_from_filecontent(self.__load_text(custom_argument.output_file_for_exit_code))
82
- pid = self.__get_number_from_filecontent(self.__load_text(custom_argument.output_file_for_pid))
83
- GeneralUtilities.ensure_directory_does_not_exist(custom_argument.tempdir)
84
- result = (exit_code, stdout, stderr, pid)
85
- return result
86
-
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) -> tuple[int, str, str, int]:
89
- process: Popen = self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument)
90
- return self.wait(process, custom_argument)
91
-
92
- @GeneralUtilities.check_arguments
93
- def run_program(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None) -> tuple[int, str, str, int]:
94
- return self.run_program_argsasarray(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument)
95
-
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) -> int:
98
- return self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument).pid
99
-
100
- @GeneralUtilities.check_arguments
101
- def run_program_async(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None) -> int:
102
- return self.run_program_argsasarray_async(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument)
103
-
104
- @GeneralUtilities.check_arguments
105
- def __get_number_from_filecontent(self, filecontent: str) -> int:
106
- for line in filecontent.splitlines():
107
- try:
108
- striped_line = GeneralUtilities.strip_new_line_character(line)
109
- result = int(striped_line)
110
- return result
111
- except:
112
- pass
113
- raise ValueError(f"'{filecontent}' does not containe an int-line")
114
-
115
- @GeneralUtilities.check_arguments
116
- def __load_text(self, file: str) -> str:
117
- if os.path.isfile(file):
118
- content = GeneralUtilities.read_text_from_file(file).replace('\r', '')
119
- os.remove(file)
120
- return content
121
- else:
122
- raise ValueError(f"File '{file}' does not exist")
1
+ import os
2
+ import base64
3
+ import tempfile
4
+ from subprocess import Popen
5
+ from uuid import uuid4
6
+
7
+ from .GeneralUtilities import GeneralUtilities
8
+ from .ProgramRunnerBase import ProgramRunnerBase
9
+ from .ProgramRunnerPopen import ProgramRunnerPopen
10
+
11
+
12
+ class CustomEpewArgument:
13
+
14
+ print_errors_as_information: bool
15
+ log_file: str
16
+ timeoutInSeconds: int
17
+ addLogOverhead: bool
18
+ title: str
19
+ log_namespace: str
20
+ verbosity: int
21
+ arguments_for_log: list[str]
22
+ tempdir = os.path.join(tempfile.gettempdir(), str(uuid4()))
23
+ stdoutfile = tempdir + ".epew.stdout.txt"
24
+ stderrfile = tempdir + ".epew.stderr.txt"
25
+ exitcodefile = tempdir + ".epew.exitcode.txt"
26
+ pidfile = tempdir + ".epew.pid.txt"
27
+
28
+ def __init__(self, print_errors_as_information: bool, log_file: str, timeoutInSeconds: int, addLogOverhead: bool, title: str, log_namespace: str, verbosity: int, arguments_for_log: list[str]):
29
+ self.print_errors_as_information = print_errors_as_information
30
+ self.log_file = log_file
31
+ self.timeoutInSeconds = timeoutInSeconds
32
+ self.addLogOverhead = addLogOverhead
33
+ self.title = title
34
+ self.log_namespace = log_namespace
35
+ self.verbosity = verbosity
36
+ self.arguments_for_log = arguments_for_log
37
+
38
+
39
+ class ProgramRunnerEpew(ProgramRunnerBase):
40
+
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:
43
+ if GeneralUtilities.epew_is_available():
44
+ custom_argument: CustomEpewArgument = custom_argument
45
+ args = []
46
+
47
+ base64argument = base64.b64encode(' '.join(arguments_as_array).encode('utf-8')).decode('utf-8')
48
+ args.append(f'-p "{program}"')
49
+ args.append(f'-a {base64argument}')
50
+ args.append('-b')
51
+ args.append(f'-w "{working_directory}"')
52
+ if custom_argument.stdoutfile is not None:
53
+ args.append(f'-o {custom_argument.stdoutfile}')
54
+ if custom_argument.stderrfile is not None:
55
+ args.append(f'-e {custom_argument.stderrfile}')
56
+ if custom_argument.exitcodefile is not None:
57
+ args.append(f'-x {custom_argument.exitcodefile}')
58
+ if custom_argument.pidfile is not None:
59
+ args.append(f'-r {custom_argument.pidfile}')
60
+ args.append(f'-d {str(custom_argument.timeoutInSeconds*1000)}')
61
+ args.append(f'-t "{custom_argument.title}"')
62
+ args.append(f'-l "{custom_argument.log_namespace}"')
63
+ if not GeneralUtilities.string_is_none_or_whitespace(custom_argument.log_file):
64
+ args.append(f'-f "{custom_argument.log_file}"')
65
+ if custom_argument.print_errors_as_information:
66
+ args.append("-i")
67
+ if custom_argument.addLogOverhead:
68
+ args.append("-g")
69
+ args.append("-v "+str(custom_argument.verbosity))
70
+ return ProgramRunnerPopen().run_program_argsasarray_async_helper("epew", args, working_directory,custom_argument,interactive)
71
+ else:
72
+ raise ValueError("Epew is not available.")
73
+
74
+ # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
75
+ @GeneralUtilities.check_arguments
76
+ def wait(self, process: Popen, custom_argument: object = None) -> tuple[int, str, str, int]:
77
+ process.wait()
78
+ custom_argument: CustomEpewArgument = custom_argument
79
+ stdout = self.__load_text(custom_argument.output_file_for_stdout)
80
+ stderr = self.__load_text(custom_argument.output_file_for_stderr)
81
+ exit_code = self.__get_number_from_filecontent(self.__load_text(custom_argument.output_file_for_exit_code))
82
+ pid = self.__get_number_from_filecontent(self.__load_text(custom_argument.output_file_for_pid))
83
+ GeneralUtilities.ensure_directory_does_not_exist(custom_argument.tempdir)
84
+ result = (exit_code, stdout, stderr, pid)
85
+ return result
86
+
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)
90
+ return self.wait(process, custom_argument)
91
+
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)
95
+
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
99
+
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)
103
+
104
+ @GeneralUtilities.check_arguments
105
+ def __get_number_from_filecontent(self, filecontent: str) -> int:
106
+ for line in filecontent.splitlines():
107
+ try:
108
+ striped_line = GeneralUtilities.strip_new_line_character(line)
109
+ result = int(striped_line)
110
+ return result
111
+ except:
112
+ pass
113
+ raise ValueError(f"'{filecontent}' does not containe an int-line")
114
+
115
+ @GeneralUtilities.check_arguments
116
+ def __load_text(self, file: str) -> str:
117
+ if os.path.isfile(file):
118
+ content = GeneralUtilities.read_text_from_file(file).replace('\r', '')
119
+ os.remove(file)
120
+ return content
121
+ else:
122
+ raise ValueError(f"File '{file}' does not exist")
@@ -1,52 +1,51 @@
1
- import os
2
- from subprocess import PIPE, Popen
3
- from .GeneralUtilities import GeneralUtilities
4
- from .ProgramRunnerBase import ProgramRunnerBase
5
-
6
-
7
- class ProgramRunnerPopen(ProgramRunnerBase):
8
-
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) -> Popen:
11
- arguments_for_process = [program]
12
- arguments_for_process.extend(arguments_as_array)
13
- # "shell=True" is not allowed because it is not recommended and also something like
14
- # "ScriptCollectionCore().run_program('curl', 'https://example.com/dataset?id=1&format=json')"
15
- # would not be possible anymore because the ampersand will be treated as shell-command.
16
- cwd = os.getcwd()
17
- try:
18
- os.chdir(working_directory)
19
- result = Popen(arguments_for_process, stdout=PIPE, stderr=PIPE, shell=False) # pylint: disable=consider-using-with
20
- except FileNotFoundError as fileNotFoundError:
21
- raise FileNotFoundError(f"Starting '{program}' in '{working_directory}' resulted in a FileNotFoundError: '{fileNotFoundError.filename}'")
22
- finally:
23
- os.chdir(cwd)
24
- return result
25
-
26
- # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
27
- @GeneralUtilities.check_arguments
28
- def wait(self, process: Popen, custom_argument: object) -> tuple[int, str, str, int]:
29
- pid = process.pid
30
- stdout, stderr = process.communicate()
31
- exit_code = process.wait()
32
- stdout = GeneralUtilities.bytes_to_string(stdout).replace('\r', '')
33
- stderr = GeneralUtilities.bytes_to_string(stderr).replace('\r', '')
34
- result = (exit_code, stdout, stderr, pid)
35
- return result
36
-
37
- @GeneralUtilities.check_arguments
38
- def run_program_argsasarray(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None) -> tuple[int, str, str, int]:
39
- process: Popen = self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument)
40
- return self.wait(process, custom_argument)
41
-
42
- @GeneralUtilities.check_arguments
43
- def run_program(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None) -> tuple[int, str, str, int]:
44
- return self.run_program_argsasarray(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument)
45
-
46
- @GeneralUtilities.check_arguments
47
- def run_program_argsasarray_async(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, custom_argument: object = None) -> int:
48
- return self.run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, custom_argument).pid
49
-
50
- @GeneralUtilities.check_arguments
51
- def run_program_async(self, program: str, arguments: str = "", working_directory: str = None, custom_argument: object = None) -> int:
52
- return self.run_program_argsasarray_async(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument)
1
+ import sys
2
+ from subprocess import PIPE, Popen
3
+ from .GeneralUtilities import GeneralUtilities
4
+ from .ProgramRunnerBase import ProgramRunnerBase
5
+
6
+
7
+ class ProgramRunnerPopen(ProgramRunnerBase):
8
+
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:
11
+ arguments_for_process = [program]
12
+ arguments_for_process.extend(arguments_as_array)
13
+ # "shell=True" is not allowed because it is not recommended and also something like
14
+ # "ScriptCollectionCore().run_program('curl', 'https://example.com/dataset?id=1&format=json')"
15
+ # would not be possible anymore because the ampersand will be treated as shell-command.
16
+ try:
17
+ if interactive:
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
+ else:
20
+ result = Popen(arguments_for_process, cwd=working_directory, stdout=PIPE, stderr=PIPE, shell=False, text=True) # pylint: disable=consider-using-with
21
+ except FileNotFoundError as fileNotFoundError:
22
+ raise FileNotFoundError(f"Starting '{program}' in '{working_directory}' resulted in a FileNotFoundError: '{fileNotFoundError.filename}'")
23
+ return result
24
+
25
+ # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
26
+ @GeneralUtilities.check_arguments
27
+ def wait(self, process: Popen, custom_argument: object) -> tuple[int, str, str, int]:
28
+ pid = process.pid
29
+ stdout, stderr = process.communicate()
30
+ exit_code = process.wait()
31
+ stdout = GeneralUtilities.bytes_to_string(stdout).replace('\r', '')
32
+ stderr = GeneralUtilities.bytes_to_string(stderr).replace('\r', '')
33
+ result = (exit_code, stdout, stderr, pid)
34
+ return result
35
+
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)
39
+ return self.wait(process, custom_argument)
40
+
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]:
43
+ return self.run_program_argsasarray(program, GeneralUtilities.arguments_to_array(arguments), working_directory, custom_argument)
44
+
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
48
+
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)