diff --git a/CHANGELOG.md b/CHANGELOG.md index befdf6dd5a2034cd620e92490ee52197b352fce2..327ab9f4b9cf9b23cd30dd7245279fcec68788a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1,4 @@ # v2.7.18 + +* reformatted `ProcessFailed` exception +* added an option not to check the return code \ No newline at end of file diff --git a/satella/__init__.py b/satella/__init__.py index fa287e484979e19a7d23db215c3e6b70c675e73a..6806d01093fc5bd00981f5ea99f1828b72679739 100644 --- a/satella/__init__.py +++ b/satella/__init__.py @@ -1 +1 @@ -__version__ = '2.7.18_a1' +__version__ = '2.7.18' diff --git a/satella/exceptions.py b/satella/exceptions.py index 320f13d062cb3945952b9aedd5382b35a788b144..5830784f5744c93165e1a224b3763b2d1218eaf6 100644 --- a/satella/exceptions.py +++ b/satella/exceptions.py @@ -162,8 +162,16 @@ class LockIsHeld(ResourceLocked): class ProcessFailed(BaseSatellaError): - """A process finished with other result code that it was requested""" + """A process finished with other result code that it was requested - def __init__(self, rc: int): - super().__init__(rc) + :param rc: return code of the process + :param stdout_so_far: process' stdout gathered so far + """ + + def __init__(self, rc: int, stdout_so_far: tp.Union[bytes, str]): + super().__init__(rc, stdout_so_far) self.rc = rc + self.stdout_so_far = stdout_so_far + + def __str__(self): + return 'ProcessFailed(%s)' % (self.rc, ) diff --git a/satella/processes.py b/satella/processes.py index eea97a3a1614f0121ccce123ad8c397a3a2b26c4..6ae160b4d66aa1d6d9bed2b66b837adb66717e98 100644 --- a/satella/processes.py +++ b/satella/processes.py @@ -22,7 +22,8 @@ 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]: + expected_return_code: tp.Optional[int] = None, + **kwargs) -> tp.Union[bytes, str]: """ Call a process and return it's stdout. @@ -36,7 +37,8 @@ def call_and_return_stdout(args: tp.Union[str, tp.List[str]], 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 + returns anything else, ProcessFailed will be raise. If left default (None) return code won't be checked + at all :raises ProcessFailed: process' result code was different from the requested """ if isinstance(args, str): @@ -56,13 +58,14 @@ def call_and_return_stdout(args: tp.Union[str, tp.List[str]], proc.wait() reader_thread.join() - if proc.returncode != expected_return_code: - raise ProcessFailed(proc.returncode) + if encoding is None: + result = b''.join(stdout_list) else: - if encoding is None: - return b''.join(stdout_list) - else: + result = ''.join((row.decode(encoding) for row in stdout_list)) - return ''.join((row.decode(encoding) for row in stdout_list)) + if expected_return_code is not None: + if proc.returncode != expected_return_code: + raise ProcessFailed(proc.returncode, result) + return result diff --git a/tests/test_processes.py b/tests/test_processes.py index 533fcdb3a5b0f2f35c28917d86ed48b2b3070841..f53dc142bae569c8f7bf64b1467022603ea48bfb 100644 --- a/tests/test_processes.py +++ b/tests/test_processes.py @@ -6,7 +6,7 @@ from satella.processes import call_and_return_stdout class TestProcesses(unittest.TestCase): @unittest.skipIf('win' in sys.platform, 'Running on Windows') def test_return_stdout(self): - output = call_and_return_stdout('ls .', shell=True, timeout=3) + output = call_and_return_stdout('ls .', shell=True, timeout=3, expected_return_code=0) self.assertIn(b'requirements.txt', output) @unittest.skipIf('win' in sys.platform or sys.version_info.minor < 6, 'Running on Windows or Python 3.5')