Execute |command| and return the returncode and the output
( # pylint: disable=too-many-locals,too-many-branches
command: List[str],
*args,
expect_zero: bool = True,
timeout: int = None,
write_to_stdout=False,
# If not set, will default to PIPE.
output_file=None,
# Not True by default because we can't always set group on processes.
kill_children: bool = False,
**kwargs)
| 67 | |
| 68 | |
| 69 | def execute( # pylint: disable=too-many-locals,too-many-branches |
| 70 | command: List[str], |
| 71 | *args, |
| 72 | expect_zero: bool = True, |
| 73 | timeout: int = None, |
| 74 | write_to_stdout=False, |
| 75 | # If not set, will default to PIPE. |
| 76 | output_file=None, |
| 77 | # Not True by default because we can't always set group on processes. |
| 78 | kill_children: bool = False, |
| 79 | **kwargs) -> ProcessResult: |
| 80 | """Execute |command| and return the returncode and the output""" |
| 81 | if write_to_stdout: |
| 82 | # Don't set stdout, it's default value None, causes it to be set to |
| 83 | # stdout. |
| 84 | assert output_file is None |
| 85 | elif not output_file: |
| 86 | output_file = subprocess.PIPE |
| 87 | |
| 88 | kwargs['stdout'] = subprocess.PIPE |
| 89 | kwargs['stderr'] = subprocess.PIPE |
| 90 | if kill_children: |
| 91 | kwargs['preexec_fn'] = os.setsid |
| 92 | |
| 93 | process = subprocess.Popen(command, shell=False, *args, **kwargs) |
| 94 | process_group_id = os.getpgid(process.pid) |
| 95 | |
| 96 | wrapped_process = WrappedPopen(process) |
| 97 | if timeout is not None: |
| 98 | kill_thread = _start_kill_thread(wrapped_process, kill_children, |
| 99 | timeout) |
| 100 | _, err = process.communicate() |
| 101 | |
| 102 | if timeout is not None: |
| 103 | kill_thread.cancel() |
| 104 | elif kill_children: |
| 105 | # elif because the kill_thread will kill children if needed. |
| 106 | _kill_process_group(process_group_id) |
| 107 | |
| 108 | retcode = process.returncode |
| 109 | |
| 110 | if err is not None: |
| 111 | err = err.decode('utf-8', errors='ignore') |
| 112 | |
| 113 | if expect_zero and retcode != 0 and not wrapped_process.timed_out: |
| 114 | raise subprocess.CalledProcessError(retcode, command) |
| 115 | |
| 116 | return ProcessResult(retcode, err, wrapped_process.timed_out) |
nothing calls this directly
no test coverage detected