diff --git a/satella/processes.py b/satella/processes.py index af56d19066b9656220807de8be0a74421c463fc0..c0dfbd9f477b4caeff1db2bdacb96c2bd5b89abd 100644 --- a/satella/processes.py +++ b/satella/processes.py @@ -19,15 +19,20 @@ def read_nowait(process: subprocess.Popen, output_list: tp.List[str]): def call_and_return_stdout(args: tp.Union[str, tp.List[str]], timeout: tp.Optional[int] = None, + encoding: tp.Optional[str] = None, expected_return_code: int = 0, **kwargs) -> tp.Union[bytes, str]: """ Call a process and return it's stdout. Everything in kwargs will be passed to subprocess.Popen + A bytes object will be returned if encoding is not defined, else stdout will be decoded + according to specified encoding + :param args: arguments to run the program with. If passed a string, it will be split on space. :param timeout: amount of seconds to wait for the process result. If process does not complete within this time, it will be sent a SIGKILL + :param encoding: encoding with which to decode stdout. If none is passed, it will be returned as a bytes object :param expected_return_code: an expected return code of this process. 0 is the default. If process returns anything else, ProcessFailed will be raise :raises ProcessFailed: process' result code was different from the requested @@ -47,13 +52,15 @@ def call_and_return_stdout(args: tp.Union[str, tp.List[str]], except subprocess.TimeoutExpired: proc.kill() proc.wait() + reader_thread.join() if proc.returncode != expected_return_code: raise ProcessFailed(proc.returncode) else: - if kwargs.get('encoding', None) is None: + if encoding is None: return b''.join(stdout_list) else: - return ''.join(stdout_list) + + return ''.join((row.decode(encoding) for row in stdout_list))