multiCMD 1.15__tar.gz → 1.16__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: multiCMD
3
- Version: 1.15
3
+ Version: 1.16
4
4
  Summary: Run commands simultaneously
5
5
  Home-page: https://github.com/yufei-pan/multiCMD
6
6
  Author: Yufei Pan
@@ -32,6 +32,10 @@ Can be used in bash scripts for automation actions.
32
32
 
33
33
  Also able to be imported and act as a wrapper for subprocess.
34
34
 
35
+ Use return_object=True with run_commands or run_command to get the Task Object (definition below)
36
+
37
+ Use quiet=True and wait_for_return=False to create a daemon thread that async updates the return list / objects when return comes
38
+
35
39
  For each process, it will initialize a thread if using -m/--max_threads > 1
36
40
 
37
41
  For each thread, it will use subprocess lib to open a process for the command task
@@ -69,8 +73,9 @@ Run multiple commands in parallel
69
73
  positional arguments:
70
74
  command commands to run
71
75
 
72
- optional arguments:
76
+ options:
73
77
  -h, --help show this help message and exit
78
+ -p, --parse Parse ranged input and expand them into multiple commands
74
79
  -t timeout, --timeout timeout
75
80
  timeout for each command
76
81
  -m max_threads, --max_threads max_threads
@@ -81,12 +86,12 @@ optional arguments:
81
86
 
82
87
  ```python
83
88
  def run_commands(commands, timeout=0,max_threads=1,quiet=False,dry_run=False,with_stdErr=False,
84
- return_code_only=False,return_object=False):
89
+ return_code_only=False,return_object=False, parse = False, wait_for_return = True):
85
90
  '''
86
91
  Run multiple commands in parallel
87
92
 
88
93
  @params:
89
- commands: A list of commands to run
94
+ commands: A list of commands to run ( list[str] | list[list[str]] )
90
95
  timeout: The timeout for each command
91
96
  max_threads: The maximum number of threads to use
92
97
  quiet: Whether to suppress output
@@ -94,12 +99,14 @@ def run_commands(commands, timeout=0,max_threads=1,quiet=False,dry_run=False,wit
94
99
  with_stdErr: Whether to append the standard error output to the standard output
95
100
  return_code_only: Whether to return only the return code
96
101
  return_object: Whether to return the Task object
102
+ parse: Whether to parse ranged input
103
+ wait_for_return: Whether to wait for the return of the commands
97
104
 
98
105
  @returns:
99
106
  list: The output of the commands ( list[None] | list[int] | list[list[str]] | list[Task] )
100
- '''
107
+ '''
101
108
  def run_command(command, timeout=0,max_threads=1,quiet=False,dry_run=False,with_stdErr=False,
102
- return_code_only=False,return_object=False):
109
+ return_code_only=False,return_object=False,wait_for_return=True):
103
110
  '''
104
111
  Run a command
105
112
 
@@ -112,10 +119,22 @@ def run_command(command, timeout=0,max_threads=1,quiet=False,dry_run=False,with_
112
119
  with_stdErr: Whether to append the standard error output to the standard output
113
120
  return_code_only: Whether to return only the return code
114
121
  return_object: Whether to return the Task object
122
+ wait_for_return: Whether to wait for the return of the command
115
123
 
116
124
  @returns:
117
125
  None | int | list[str] | Task: The output of the command
118
126
  '''
127
+ def join_threads(threads=__running_threads,timeout=None):
128
+ '''
129
+ Join threads
130
+
131
+ @params:
132
+ threads: The threads to join
133
+ timeout: The timeout
134
+
135
+ @returns:
136
+ None
137
+ '''
119
138
  def input_with_timeout_and_countdown(timeout, prompt='Please enter your selection'):
120
139
  """
121
140
  Read an input from the user with a timeout and a countdown.
@@ -7,6 +7,10 @@ Can be used in bash scripts for automation actions.
7
7
 
8
8
  Also able to be imported and act as a wrapper for subprocess.
9
9
 
10
+ Use return_object=True with run_commands or run_command to get the Task Object (definition below)
11
+
12
+ Use quiet=True and wait_for_return=False to create a daemon thread that async updates the return list / objects when return comes
13
+
10
14
  For each process, it will initialize a thread if using -m/--max_threads > 1
11
15
 
12
16
  For each thread, it will use subprocess lib to open a process for the command task
@@ -44,8 +48,9 @@ Run multiple commands in parallel
44
48
  positional arguments:
45
49
  command commands to run
46
50
 
47
- optional arguments:
51
+ options:
48
52
  -h, --help show this help message and exit
53
+ -p, --parse Parse ranged input and expand them into multiple commands
49
54
  -t timeout, --timeout timeout
50
55
  timeout for each command
51
56
  -m max_threads, --max_threads max_threads
@@ -56,12 +61,12 @@ optional arguments:
56
61
 
57
62
  ```python
58
63
  def run_commands(commands, timeout=0,max_threads=1,quiet=False,dry_run=False,with_stdErr=False,
59
- return_code_only=False,return_object=False):
64
+ return_code_only=False,return_object=False, parse = False, wait_for_return = True):
60
65
  '''
61
66
  Run multiple commands in parallel
62
67
 
63
68
  @params:
64
- commands: A list of commands to run
69
+ commands: A list of commands to run ( list[str] | list[list[str]] )
65
70
  timeout: The timeout for each command
66
71
  max_threads: The maximum number of threads to use
67
72
  quiet: Whether to suppress output
@@ -69,12 +74,14 @@ def run_commands(commands, timeout=0,max_threads=1,quiet=False,dry_run=False,wit
69
74
  with_stdErr: Whether to append the standard error output to the standard output
70
75
  return_code_only: Whether to return only the return code
71
76
  return_object: Whether to return the Task object
77
+ parse: Whether to parse ranged input
78
+ wait_for_return: Whether to wait for the return of the commands
72
79
 
73
80
  @returns:
74
81
  list: The output of the commands ( list[None] | list[int] | list[list[str]] | list[Task] )
75
- '''
82
+ '''
76
83
  def run_command(command, timeout=0,max_threads=1,quiet=False,dry_run=False,with_stdErr=False,
77
- return_code_only=False,return_object=False):
84
+ return_code_only=False,return_object=False,wait_for_return=True):
78
85
  '''
79
86
  Run a command
80
87
 
@@ -87,10 +94,22 @@ def run_command(command, timeout=0,max_threads=1,quiet=False,dry_run=False,with_
87
94
  with_stdErr: Whether to append the standard error output to the standard output
88
95
  return_code_only: Whether to return only the return code
89
96
  return_object: Whether to return the Task object
97
+ wait_for_return: Whether to wait for the return of the command
90
98
 
91
99
  @returns:
92
100
  None | int | list[str] | Task: The output of the command
93
101
  '''
102
+ def join_threads(threads=__running_threads,timeout=None):
103
+ '''
104
+ Join threads
105
+
106
+ @params:
107
+ threads: The threads to join
108
+ timeout: The timeout
109
+
110
+ @returns:
111
+ None
112
+ '''
94
113
  def input_with_timeout_and_countdown(timeout, prompt='Please enter your selection'):
95
114
  """
96
115
  Read an input from the user with a timeout and a countdown.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: multiCMD
3
- Version: 1.15
3
+ Version: 1.16
4
4
  Summary: Run commands simultaneously
5
5
  Home-page: https://github.com/yufei-pan/multiCMD
6
6
  Author: Yufei Pan
@@ -32,6 +32,10 @@ Can be used in bash scripts for automation actions.
32
32
 
33
33
  Also able to be imported and act as a wrapper for subprocess.
34
34
 
35
+ Use return_object=True with run_commands or run_command to get the Task Object (definition below)
36
+
37
+ Use quiet=True and wait_for_return=False to create a daemon thread that async updates the return list / objects when return comes
38
+
35
39
  For each process, it will initialize a thread if using -m/--max_threads > 1
36
40
 
37
41
  For each thread, it will use subprocess lib to open a process for the command task
@@ -69,8 +73,9 @@ Run multiple commands in parallel
69
73
  positional arguments:
70
74
  command commands to run
71
75
 
72
- optional arguments:
76
+ options:
73
77
  -h, --help show this help message and exit
78
+ -p, --parse Parse ranged input and expand them into multiple commands
74
79
  -t timeout, --timeout timeout
75
80
  timeout for each command
76
81
  -m max_threads, --max_threads max_threads
@@ -81,12 +86,12 @@ optional arguments:
81
86
 
82
87
  ```python
83
88
  def run_commands(commands, timeout=0,max_threads=1,quiet=False,dry_run=False,with_stdErr=False,
84
- return_code_only=False,return_object=False):
89
+ return_code_only=False,return_object=False, parse = False, wait_for_return = True):
85
90
  '''
86
91
  Run multiple commands in parallel
87
92
 
88
93
  @params:
89
- commands: A list of commands to run
94
+ commands: A list of commands to run ( list[str] | list[list[str]] )
90
95
  timeout: The timeout for each command
91
96
  max_threads: The maximum number of threads to use
92
97
  quiet: Whether to suppress output
@@ -94,12 +99,14 @@ def run_commands(commands, timeout=0,max_threads=1,quiet=False,dry_run=False,wit
94
99
  with_stdErr: Whether to append the standard error output to the standard output
95
100
  return_code_only: Whether to return only the return code
96
101
  return_object: Whether to return the Task object
102
+ parse: Whether to parse ranged input
103
+ wait_for_return: Whether to wait for the return of the commands
97
104
 
98
105
  @returns:
99
106
  list: The output of the commands ( list[None] | list[int] | list[list[str]] | list[Task] )
100
- '''
107
+ '''
101
108
  def run_command(command, timeout=0,max_threads=1,quiet=False,dry_run=False,with_stdErr=False,
102
- return_code_only=False,return_object=False):
109
+ return_code_only=False,return_object=False,wait_for_return=True):
103
110
  '''
104
111
  Run a command
105
112
 
@@ -112,10 +119,22 @@ def run_command(command, timeout=0,max_threads=1,quiet=False,dry_run=False,with_
112
119
  with_stdErr: Whether to append the standard error output to the standard output
113
120
  return_code_only: Whether to return only the return code
114
121
  return_object: Whether to return the Task object
122
+ wait_for_return: Whether to wait for the return of the command
115
123
 
116
124
  @returns:
117
125
  None | int | list[str] | Task: The output of the command
118
126
  '''
127
+ def join_threads(threads=__running_threads,timeout=None):
128
+ '''
129
+ Join threads
130
+
131
+ @params:
132
+ threads: The threads to join
133
+ timeout: The timeout
134
+
135
+ @returns:
136
+ None
137
+ '''
119
138
  def input_with_timeout_and_countdown(timeout, prompt='Please enter your selection'):
120
139
  """
121
140
  Read an input from the user with a timeout and a countdown.
@@ -11,9 +11,10 @@ import string
11
11
  import re
12
12
  import itertools
13
13
 
14
- version = '1.15'
14
+ version = '1.16'
15
15
  __version__ = version
16
16
 
17
+ __running_threads = []
17
18
  class Task:
18
19
  def __init__(self, command):
19
20
  self.command = command
@@ -21,7 +22,11 @@ class Task:
21
22
  self.stdout = []
22
23
  self.stderr = []
23
24
  def __iter__(self):
24
- return zip(['command', 'returncode', 'stdout', 'stderr'], [self.name, self.command, self.returncode, self.stdout, self.stderr])
25
+ return zip(['command', 'returncode', 'stdout', 'stderr'], [self.command, self.returncode, self.stdout, self.stderr])
26
+ def __repr__(self):
27
+ return f'Task(command={self.command}, returncode={self.returncode}, stdout={self.stdout}, stderr={self.stderr})'
28
+ def __str__(self):
29
+ return str(dict(self))
25
30
 
26
31
  def _expand_ranges(inStr):
27
32
  '''
@@ -177,11 +182,11 @@ def __run_command(task,sem, timeout=60, quiet=False,dry_run=False,with_stdErr=Fa
177
182
  #host.stdout = []
178
183
  proc = subprocess.Popen(task.command,stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE)
179
184
  # create a thread to handle stdout
180
- stdout_thread = threading.Thread(target=__handle_stream, args=(proc.stdout,task.stdout,pre,post,quiet))
185
+ stdout_thread = threading.Thread(target=__handle_stream, args=(proc.stdout,task.stdout,pre,post,quiet),daemon=True)
181
186
  stdout_thread.start()
182
187
  # create a thread to handle stderr
183
188
  #host.stderr = []
184
- stderr_thread = threading.Thread(target=__handle_stream, args=(proc.stderr,task.stderr,pre,post,quiet))
189
+ stderr_thread = threading.Thread(target=__handle_stream, args=(proc.stderr,task.stderr,pre,post,quiet),daemon=True)
185
190
  stderr_thread.start()
186
191
  # Monitor the subprocess and terminate it after the timeout
187
192
  start_time = time.time()
@@ -220,7 +225,7 @@ def __run_command(task,sem, timeout=60, quiet=False,dry_run=False,with_stdErr=Fa
220
225
  return task.stdout
221
226
 
222
227
  def run_command(command, timeout=0,max_threads=1,quiet=False,dry_run=False,with_stdErr=False,
223
- return_code_only=False,return_object=False):
228
+ return_code_only=False,return_object=False,wait_for_return=True):
224
229
  '''
225
230
  Run a command
226
231
 
@@ -233,11 +238,14 @@ def run_command(command, timeout=0,max_threads=1,quiet=False,dry_run=False,with_
233
238
  with_stdErr: Whether to append the standard error output to the standard output
234
239
  return_code_only: Whether to return only the return code
235
240
  return_object: Whether to return the Task object
241
+ wait_for_return: Whether to wait for the return of the command
236
242
 
237
243
  @returns:
238
244
  None | int | list[str] | Task: The output of the command
239
245
  '''
240
- return run_commands([command], timeout, max_threads, quiet, dry_run, with_stdErr, return_code_only, return_object)[0]
246
+ return run_commands(commands=[command], timeout=timeout, max_threads=max_threads, quiet=quiet,
247
+ dry_run=dry_run, with_stdErr=with_stdErr, return_code_only=return_code_only,
248
+ return_object=return_object,parse=False,wait_for_return=wait_for_return)[0]
241
249
 
242
250
  def __format_command(command,expand = False):
243
251
  '''
@@ -275,9 +283,8 @@ def __format_command(command,expand = False):
275
283
  else:
276
284
  return __format_command(str(command),expand=expand)
277
285
 
278
-
279
286
  def run_commands(commands, timeout=0,max_threads=1,quiet=False,dry_run=False,with_stdErr=False,
280
- return_code_only=False,return_object=False, parse = False):
287
+ return_code_only=False,return_object=False, parse = False, wait_for_return = True):
281
288
  '''
282
289
  Run multiple commands in parallel
283
290
 
@@ -291,6 +298,7 @@ def run_commands(commands, timeout=0,max_threads=1,quiet=False,dry_run=False,wit
291
298
  return_code_only: Whether to return only the return code
292
299
  return_object: Whether to return the Task object
293
300
  parse: Whether to parse ranged input
301
+ wait_for_return: Whether to wait for the return of the commands
294
302
 
295
303
  @returns:
296
304
  list: The output of the commands ( list[None] | list[int] | list[list[str]] | list[Task] )
@@ -304,13 +312,16 @@ def run_commands(commands, timeout=0,max_threads=1,quiet=False,dry_run=False,wit
304
312
  # run the tasks with max_threads. if max_threads is 0, use the number of commands
305
313
  if max_threads < 1:
306
314
  max_threads = len(formatedCommands)
307
- if max_threads > 1:
315
+ if max_threads > 1 or not wait_for_return:
308
316
  sem = threading.Semaphore(max_threads) # Limit concurrent sessions
309
- threads = [threading.Thread(target=__run_command, args=(task,sem,timeout,quiet,dry_run,...)) for task in tasks]
317
+ threads = [threading.Thread(target=__run_command, args=(task,sem,timeout,quiet,dry_run,...),daemon=True) for task in tasks]
310
318
  for thread in threads:
311
319
  thread.start()
312
- for thread in threads:
313
- thread.join()
320
+ if wait_for_return:
321
+ for thread in threads:
322
+ thread.join()
323
+ else:
324
+ __running_threads.extend(threads)
314
325
  else:
315
326
  # just process the commands sequentially
316
327
  sem = threading.Semaphore(1)
@@ -326,6 +337,20 @@ def run_commands(commands, timeout=0,max_threads=1,quiet=False,dry_run=False,wit
326
337
  else:
327
338
  return [task.stdout for task in tasks]
328
339
 
340
+ def join_threads(threads=__running_threads,timeout=None):
341
+ '''
342
+ Join threads
343
+
344
+ @params:
345
+ threads: The threads to join
346
+ timeout: The timeout
347
+
348
+ @returns:
349
+ None
350
+ '''
351
+ for thread in threads:
352
+ thread.join(timeout=timeout)
353
+
329
354
  def input_with_timeout_and_countdown(timeout, prompt='Please enter your selection'):
330
355
  """
331
356
  Read an input from the user with a timeout and a countdown.
File without changes
File without changes
File without changes