Coverage for .tox/cov/lib/python3.11/site-packages/confattr/subprocess_pipe.py: 100%
32 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-10 20:18 +0200
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-10 20:18 +0200
1#!./runmodule.sh
3import subprocess
4import typing
5from collections.abc import Sequence, Mapping
7PIPE = '|'
9T = typing.TypeVar('T')
10CompletedProcess = subprocess.CompletedProcess
12def run_and_pipe(cmds: 'Sequence[str]', *, get_output: bool = False, env: 'Mapping[str, str]|None' = None) -> 'subprocess.CompletedProcess[bytes]':
13 '''
14 Run an external program and return when the program is finished.
16 :param cmds: One or several commands to be executed. If several commands are passed they are seperated by a '|' and stdout of the former command is piped to stdin of the following command.
17 :param env: The environment variables to be passed to the subprocess. If env is None :py:data:`os.environ` is used.
18 :param get_output: Make stdout and stderr available in the returned completed process object.
19 :return: The completed process
20 :raises OSError: e.g. if the program was not found
21 :raises CalledProcessError: if the called program failed
23 https://docs.python.org/3/library/subprocess.html#exceptions
24 '''
25 # I am not using shell=True because that is platform dependend
26 # and shlex is for UNIX like shells only, so it may not work on Windows
27 if get_output:
28 def run(cmd: 'Sequence[str]', input: 'bytes|None' = None) -> 'subprocess.CompletedProcess[bytes]':
29 return subprocess.run(cmd, env=env, input=input, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
30 else:
31 def run(cmd: 'Sequence[str]', input: 'bytes|None' = None) -> 'subprocess.CompletedProcess[bytes]':
32 return subprocess.run(cmd, env=env, input=input)
34 cmd_list = split_list(cmds, PIPE)
35 n = len(cmd_list)
36 if n == 1:
37 return run(cmd_list[0])
39 p = subprocess.run(cmd_list[0], env=env, stdout=subprocess.PIPE)
40 for cmd in cmd_list[1:-1]:
41 p = subprocess.run(cmd, env=env, input=p.stdout, stdout=subprocess.PIPE)
42 return run(cmd_list[-1], input=p.stdout)
44def split_list(l: 'Sequence[T]', sep: T) -> 'Sequence[Sequence[T]]':
45 '''
46 Like str.split but for lists/tuples.
47 Splits a sequence into several sequences.
48 '''
49 out: 'list[Sequence[T]]' = []
50 i0 = 0
51 while True:
52 try:
53 i1 = l.index(sep, i0)
54 except ValueError:
55 break
56 out.append(l[i0:i1])
57 i0 = i1 + 1
58 out.append(l[i0:])
59 return out