summaryrefslogtreecommitdiffstats
path: root/rtemstoolkit/execute.py
diff options
context:
space:
mode:
Diffstat (limited to 'rtemstoolkit/execute.py')
-rwxr-xr-xrtemstoolkit/execute.py129
1 files changed, 110 insertions, 19 deletions
diff --git a/rtemstoolkit/execute.py b/rtemstoolkit/execute.py
index ed81589..c7d8134 100755
--- a/rtemstoolkit/execute.py
+++ b/rtemstoolkit/execute.py
@@ -37,9 +37,11 @@
from __future__ import print_function
import functools
+import codecs
import io
import os
import re
+import shlex
import sys
import subprocess
import threading
@@ -124,6 +126,14 @@ class execute(object):
self.timing_out = False
self.proc = None
+ @staticmethod
+ def _shlex_join(elements):
+ try:
+ return shlex.join(elements)
+ except AttributeError:
+ # Python older than 3.8 does not have shlex.join
+ return ' '.join(elements)
+
def capture(self, proc, command = 'pipe', timeout = None):
"""Create 3 threads to read stdout and stderr and send to the output handler
and call an input handler is provided. Based on the 'communicate' code
@@ -194,6 +204,10 @@ class execute(object):
stacktraces.trace()
if trace_threads:
print('execute:_readthread: start')
+ if sys.stdout.encoding is not None:
+ decoder = codecs.getincrementaldecoder(sys.stdout.encoding)()
+ else:
+ decoder = None
count = 0
line = ''
try:
@@ -213,8 +227,8 @@ class execute(object):
_output_line(line + '\n', exe, prefix, out, count)
break
# str and bytes are the same type in Python2
- if type(data) is not str and type(data) is bytes:
- data = data.decode(sys.stdout.encoding)
+ if decoder is not None and type(data) is not str and type(data) is bytes:
+ data = decoder.decode(data)
last_ch = data[-1]
sd = (line + data).split('\n')
if last_ch != '\n':
@@ -355,10 +369,17 @@ class execute(object):
a string."""
if self.output is None:
raise error.general('capture needs an output handler')
- cs = command
- if type(command) is list:
- def add(x, y): return x + ' ' + str(y)
- cs = functools.reduce(add, command, '')[1:]
+ # If a string split and not a shell command split
+ if not shell and isinstance(command, str):
+ command = shlex.split(command)
+ if shell and isinstance(command, list):
+ command = execute._shlex_join(command)
+ if self.shell_exe:
+ command = self.shell_exe + ' ' + command
+ if isinstance(command, list):
+ cs = execute._shlex_join(command)
+ else:
+ cs = command
what = 'spawn'
if shell:
what = 'shell'
@@ -389,11 +410,50 @@ class execute(object):
r, e = os.path.splitext(command[0])
if e not in ['.exe', '.com', '.bat']:
command[0] = command[0] + '.exe'
- proc = subprocess.Popen(command, shell = shell,
- cwd = cwd, env = env,
- stdin = stdin, stdout = stdout,
- stderr = stderr,
- close_fds = False)
+ pipe_commands = []
+ if shell:
+ pipe_commands.append(command)
+ else:
+ # See if there is a pipe operator in the command. If present
+ # split the commands by the pipe and run them with the pipe.
+ # if no pipe it is the normal stdin and stdout
+ current_command = []
+ for cmd in command:
+ if cmd == '|':
+ pipe_commands.append(current_command)
+ current_command = []
+ else:
+ current_command.append(cmd)
+ pipe_commands.append(current_command)
+ proc = None
+ if len(pipe_commands) == 1:
+ cmd = pipe_commands[0]
+ proc = subprocess.Popen(
+ cmd, shell = shell,
+ cwd = cwd, env = env,
+ stdin = stdin, stdout = stdout,
+ stderr = stderr,
+ close_fds = False)
+ else:
+ for i, cmd in enumerate(pipe_commands):
+ if i == 0:
+ proc = subprocess.Popen(
+ cmd, shell=shell,
+ cwd=cwd, env=env,
+ stdin=stdin, stdout=subprocess.PIPE)
+ elif i == len(pipe_commands) - 1:
+ proc = subprocess.Popen(
+ cmd, shell=shell,
+ cwd=cwd, env=env,
+ stdin=proc.stdout,
+ stdout=stdout, stderr=stderr,
+ close_fds=False)
+ else:
+ proc = subprocess.Popen(
+ cmd, shell=shell,
+ cwd=cwd, env=env,
+ stdin=proc.stdout,
+ stdout=subprocess.PIPE)
if not capture:
return (0, proc)
if self.output is None:
@@ -560,16 +620,28 @@ class capture_execution(execute):
if __name__ == "__main__":
def run_tests(e, commands, use_shell):
for c in commands['shell']:
- e.shell(c)
+ ec, out = e.shell(c)
+ if ec != 0:
+ raise RuntimeError('ec = {}'.format(ec))
+ for c in commands['error']:
+ ec, out = e.shell(c)
+ if ec == 0:
+ raise RuntimeError('ec = {}'.format(ec))
for c in commands['spawn']:
- e.spawn(c)
+ ec, out = e.spawn(c)
+ if ec != 0:
+ raise RuntimeError('ec = {}'.format(ec))
for c in commands['cmd']:
if type(c) is str:
- e.command(c, shell = use_shell)
+ ec, out = e.command(c, shell = use_shell)
else:
- e.command(c[0], c[1], shell = use_shell)
+ ec, out = e.command(c[0], c[1], shell = use_shell)
+ if ec != 0:
+ raise RuntimeError('ec = {}'.format(ec))
for c in commands['csubsts']:
- e.command_subst(c[0], c[1], shell = use_shell)
+ ec, out = e.command_subst(c[0], c[1], shell = use_shell)
+ if ec != 0:
+ raise RuntimeError('ec = {}'.format(ec))
ec, proc = e.command(commands['pipe'][0], commands['pipe'][1],
capture = False, stdin = subprocess.PIPE)
if ec == 0:
@@ -583,6 +655,15 @@ if __name__ == "__main__":
proc.stdin.close()
e.capture(proc)
del proc
+ else:
+ raise RuntimeError('ec = {}'.format(ec))
+ for c in commands['open']:
+ ec, proc = e.open(c)
+ if ec == 0:
+ e.capture(proc)
+ del proc
+ else:
+ raise RuntimeError('ec = {}'.format(ec))
def capture_output(text):
print(text, end = '')
@@ -595,19 +676,29 @@ if __name__ == "__main__":
commands = {}
commands['windows'] = {}
commands['unix'] = {}
- commands['windows']['shell'] = ['cd', 'dir /w', '.\\xyz', cmd_shell_test]
+ commands['windows']['shell'] = ['cd', 'dir /w', cmd_shell_test]
+ commands['windows']['error'] = ['.\\xyz']
commands['windows']['spawn'] = ['hostname', 'hostnameZZ', ['netstat', '/e']]
commands['windows']['cmd'] = [('ipconfig'), ('nslookup', 'www.python.org')]
commands['windows']['csubsts'] = [('netstat %0', ['-a']),
('netstat %0 %1', ['-a', '-n'])]
commands['windows']['pipe'] = ('ftp', None, 'help\nquit')
- commands['unix']['shell'] = ['pwd', 'ls -las', './xyz', sh_shell_test]
- commands['unix']['spawn'] = ['ls', 'execute.pyc', ['ls', '-i']]
+ commands['windows']['open'] = [
+ ["echo", "hello rtems", "|", "findstr", "rtems"],
+ " ".join(["echo", "hello rtems", "|", "findstr", "rtems"])
+ ]
+ commands['unix']['shell'] = ['pwd', 'ls -las', sh_shell_test, 'ls -las']
+ commands['unix']['error'] = ['./xyz']
+ commands['unix']['spawn'] = ['ls', ['ls', '-i'], 'ls -l']
commands['unix']['cmd'] = [('date'), ('date', '-R'), ('date', ['-u', '+%d %D']),
('date', '-u "+%d %D %S"')]
commands['unix']['csubsts'] = [('date %0 "+%d %D %S"', ['-u']),
('date %0 %1', ['-u', '+%d %D %S'])]
commands['unix']['pipe'] = ('grep', 'hello', 'hello world')
+ commands['unix']['open'] = [
+ ["echo", "hello world", "|", "cut", "-d ", "-f2"],
+ " ".join(["echo", "hello world", "|", "cut", "-d\" \"", "-f2"])
+ ]
print(arg_list('cmd a1 a2 "a3 is a string" a4'))
print(arg_list('cmd b1 b2 "b3 is a string a4'))