forked from bugy/script-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprocess_utils.py
More file actions
95 lines (71 loc) · 2.88 KB
/
Copy pathprocess_utils.py
File metadata and controls
95 lines (71 loc) · 2.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import logging
import os
import shlex
import subprocess
from utils import file_utils
from utils import os_utils
from utils import string_utils
LOGGER = logging.getLogger('script_server.process_utils')
def invoke(command, work_dir='.', *, environment_variables=None, check_stderr=True):
if isinstance(command, str):
command = split_command(command, working_directory=work_dir)
if environment_variables is not None:
env = dict(os.environ, **environment_variables)
else:
env = None
p = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=work_dir,
env=env,
universal_newlines=True)
(output, error) = p.communicate()
result_code = p.returncode
if result_code != 0:
raise ExecutionException(result_code, error, output)
if error and check_stderr:
LOGGER.warning("Error output wasn't empty, although the command finished with code 0!")
return output
def split_command(script_command, working_directory=None):
if ' ' in script_command:
if _is_file_path(script_command, working_directory):
args = [script_command]
else:
posix = not os_utils.is_win()
args = shlex.split(script_command, posix=posix)
if not posix:
args = [string_utils.unwrap_quotes(arg) for arg in args]
else:
args = [script_command]
script_path = file_utils.normalize_path(args[0], working_directory)
if (not os.path.isabs(script_path)) or (not os.path.exists(script_path)):
script_path = args[0]
script_args = args[1:]
for i, body_arg in enumerate(script_args):
expanded = os.path.expanduser(body_arg)
if expanded != body_arg:
script_args[i] = expanded
return [script_path] + script_args
def _is_file_path(script_command_with_whitespaces, working_directory):
if script_command_with_whitespaces.startswith('"') \
or script_command_with_whitespaces.startswith("'"):
return False
file_exists = file_utils.exists(script_command_with_whitespaces, working_directory)
if file_exists:
LOGGER.warning('"%s" is a file with whitespaces'
', please wrap it with quotes to avoid ambiguity',
script_command_with_whitespaces)
return True
return False
class ExecutionException(Exception):
def __init__(self, exit_code, stderr, stdout):
message = 'Execution failed. Code ' + str(exit_code)
if stderr:
message += ': ' + stderr
elif stdout:
last_line_start = stdout.rfind('\n')
message += ': ' + stdout[last_line_start:]
super().__init__(message)
self.stdout = stdout
self.stderr = stderr
self.exit_code = exit_code