1
0
mirror of https://github.com/ARM-software/devlib.git synced 2025-01-31 02:00:45 +00:00

utils/misc: separate check_output functionality

The custom check_output function consisted of two main parts: fetching
the subprocess required for the command, and checking its output.

It is convenient to provide functions that implement these parts
distinctly, so that the output of any subprocess can be checked easily
and the creation of a typical Popen object wrapped inside
get_subprocess.
This commit is contained in:
Jonathan Paynter 2020-08-10 17:40:04 +01:00 committed by Marc Bonnici
parent dc7faf46e4
commit 1d1ba7811d

View File

@ -155,9 +155,22 @@ check_output_logger = logging.getLogger('check_output')
check_output_lock = threading.Lock()
def check_output(command, timeout=None, ignore=None, inputtext=None, **kwargs):
"""This is a version of subprocess.check_output that adds a timeout parameter to kill
the subprocess if it does not return within the specified time."""
def get_subprocess(command, **kwargs):
if 'stdout' in kwargs:
raise ValueError('stdout argument not allowed, it will be overridden.')
with check_output_lock:
process = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
preexec_fn=preexec_function,
**kwargs)
return process
def check_subprocess_output(process, timeout=None, ignore=None, inputtext=None):
output = None
error = None
# pylint: disable=too-many-branches
if ignore is None:
ignore = []
@ -166,19 +179,7 @@ def check_output(command, timeout=None, ignore=None, inputtext=None, **kwargs):
elif not isinstance(ignore, list) and ignore != 'all':
message = 'Invalid value for ignore parameter: "{}"; must be an int or a list'
raise ValueError(message.format(ignore))
if 'stdout' in kwargs:
raise ValueError('stdout argument not allowed, it will be overridden.')
with check_output_lock:
process = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
preexec_fn=preexec_function,
**kwargs)
output = None
error = None
try:
output, error = process.communicate(inputtext, timeout=timeout)
except subprocess.TimeoutExpired as e:
@ -191,14 +192,22 @@ def check_output(command, timeout=None, ignore=None, inputtext=None, **kwargs):
error = error.decode(sys.stderr.encoding or 'utf-8', "replace") if output else ''
if timeout_expired:
raise TimeoutError(command, output='\n'.join([output, error]))
raise TimeoutError(process.args, output='\n'.join([output, error]))
retcode = process.poll()
if retcode and ignore != 'all' and retcode not in ignore:
raise subprocess.CalledProcessError(retcode, command, output='\n'.join([output, error]))
raise subprocess.CalledProcessError(retcode, process.args, output='\n'.join([output, error]))
return output, error
def check_output(command, timeout=None, ignore=None, inputtext=None, **kwargs):
"""This is a version of subprocess.check_output that adds a timeout parameter to kill
the subprocess if it does not return within the specified time."""
process = get_subprocess(command, **kwargs)
return check_subprocess_output(process, timeout=timeout, inputtext=inputtext)
def walk_modules(path):
"""
Given package name, return a list of all modules (including submodules, etc)