Skip to content
Snippets Groups Projects
Commit f7d5003a authored by Piotr Maślanka's avatar Piotr Maślanka
Browse files

2.7.18 extra options for call_and_return_stdout

parent 2bb384d6
No related branches found
No related tags found
No related merge requests found
# v2.7.18 # v2.7.18
* reformatted `ProcessFailed` exception
* added an option not to check the return code
\ No newline at end of file
__version__ = '2.7.18_a1' __version__ = '2.7.18'
...@@ -162,8 +162,16 @@ class LockIsHeld(ResourceLocked): ...@@ -162,8 +162,16 @@ class LockIsHeld(ResourceLocked):
class ProcessFailed(BaseSatellaError): 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): :param rc: return code of the process
super().__init__(rc) :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.rc = rc
self.stdout_so_far = stdout_so_far
def __str__(self):
return 'ProcessFailed(%s)' % (self.rc, )
...@@ -22,7 +22,8 @@ def read_nowait(process: subprocess.Popen, output_list: tp.List[str]): ...@@ -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]], def call_and_return_stdout(args: tp.Union[str, tp.List[str]],
timeout: tp.Optional[int] = None, timeout: tp.Optional[int] = None,
encoding: tp.Optional[str] = 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. Call a process and return it's stdout.
...@@ -36,7 +37,8 @@ def call_and_return_stdout(args: tp.Union[str, tp.List[str]], ...@@ -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 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 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 :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 :raises ProcessFailed: process' result code was different from the requested
""" """
if isinstance(args, str): if isinstance(args, str):
...@@ -56,13 +58,14 @@ def call_and_return_stdout(args: tp.Union[str, tp.List[str]], ...@@ -56,13 +58,14 @@ def call_and_return_stdout(args: tp.Union[str, tp.List[str]],
proc.wait() proc.wait()
reader_thread.join() reader_thread.join()
if proc.returncode != expected_return_code: if encoding is None:
raise ProcessFailed(proc.returncode) result = b''.join(stdout_list)
else: else:
if encoding is None: result = ''.join((row.decode(encoding) for row in stdout_list))
return b''.join(stdout_list)
else:
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
...@@ -6,7 +6,7 @@ from satella.processes import call_and_return_stdout ...@@ -6,7 +6,7 @@ from satella.processes import call_and_return_stdout
class TestProcesses(unittest.TestCase): class TestProcesses(unittest.TestCase):
@unittest.skipIf('win' in sys.platform, 'Running on Windows') @unittest.skipIf('win' in sys.platform, 'Running on Windows')
def test_return_stdout(self): 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) 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') @unittest.skipIf('win' in sys.platform or sys.version_info.minor < 6, 'Running on Windows or Python 3.5')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment