##// END OF EJS Templates
shlex shouldn't parse out comments, closes #1269
Paul Ivanov -
Show More
@@ -1,194 +1,195 b''
1 1 """Common utilities for the various process_* implementations.
2 2
3 3 This file is only meant to be imported by the platform-specific implementations
4 4 of subprocess utilities, and it contains tools that are common to all of them.
5 5 """
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (C) 2010-2011 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17 import subprocess
18 18 import shlex
19 19 import sys
20 20
21 21 from IPython.utils import py3compat
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Function definitions
25 25 #-----------------------------------------------------------------------------
26 26
27 27 def read_no_interrupt(p):
28 28 """Read from a pipe ignoring EINTR errors.
29 29
30 30 This is necessary because when reading from pipes with GUI event loops
31 31 running in the background, often interrupts are raised that stop the
32 32 command from completing."""
33 33 import errno
34 34
35 35 try:
36 36 return p.read()
37 37 except IOError, err:
38 38 if err.errno != errno.EINTR:
39 39 raise
40 40
41 41
42 42 def process_handler(cmd, callback, stderr=subprocess.PIPE):
43 43 """Open a command in a shell subprocess and execute a callback.
44 44
45 45 This function provides common scaffolding for creating subprocess.Popen()
46 46 calls. It creates a Popen object and then calls the callback with it.
47 47
48 48 Parameters
49 49 ----------
50 50 cmd : str
51 51 A string to be executed with the underlying system shell (by calling
52 52 :func:`Popen` with ``shell=True``.
53 53
54 54 callback : callable
55 55 A one-argument function that will be called with the Popen object.
56 56
57 57 stderr : file descriptor number, optional
58 58 By default this is set to ``subprocess.PIPE``, but you can also pass the
59 59 value ``subprocess.STDOUT`` to force the subprocess' stderr to go into
60 60 the same file descriptor as its stdout. This is useful to read stdout
61 61 and stderr combined in the order they are generated.
62 62
63 63 Returns
64 64 -------
65 65 The return value of the provided callback is returned.
66 66 """
67 67 sys.stdout.flush()
68 68 sys.stderr.flush()
69 69 # On win32, close_fds can't be true when using pipes for stdin/out/err
70 70 close_fds = sys.platform != 'win32'
71 71 p = subprocess.Popen(cmd, shell=True,
72 72 stdin=subprocess.PIPE,
73 73 stdout=subprocess.PIPE,
74 74 stderr=stderr,
75 75 close_fds=close_fds)
76 76
77 77 try:
78 78 out = callback(p)
79 79 except KeyboardInterrupt:
80 80 print('^C')
81 81 sys.stdout.flush()
82 82 sys.stderr.flush()
83 83 out = None
84 84 finally:
85 85 # Make really sure that we don't leave processes behind, in case the
86 86 # call above raises an exception
87 87 # We start by assuming the subprocess finished (to avoid NameErrors
88 88 # later depending on the path taken)
89 89 if p.returncode is None:
90 90 try:
91 91 p.terminate()
92 92 p.poll()
93 93 except OSError:
94 94 pass
95 95 # One last try on our way out
96 96 if p.returncode is None:
97 97 try:
98 98 p.kill()
99 99 except OSError:
100 100 pass
101 101
102 102 return out
103 103
104 104
105 105 def getoutput(cmd):
106 106 """Return standard output of executing cmd in a shell.
107 107
108 108 Accepts the same arguments as os.system().
109 109
110 110 Parameters
111 111 ----------
112 112 cmd : str
113 113 A command to be executed in the system shell.
114 114
115 115 Returns
116 116 -------
117 117 stdout : str
118 118 """
119 119
120 120 out = process_handler(cmd, lambda p: p.communicate()[0], subprocess.STDOUT)
121 121 if out is None:
122 122 return ''
123 123 return py3compat.bytes_to_str(out)
124 124
125 125
126 126 def getoutputerror(cmd):
127 127 """Return (standard output, standard error) of executing cmd in a shell.
128 128
129 129 Accepts the same arguments as os.system().
130 130
131 131 Parameters
132 132 ----------
133 133 cmd : str
134 134 A command to be executed in the system shell.
135 135
136 136 Returns
137 137 -------
138 138 stdout : str
139 139 stderr : str
140 140 """
141 141
142 142 out_err = process_handler(cmd, lambda p: p.communicate())
143 143 if out_err is None:
144 144 return '', ''
145 145 out, err = out_err
146 146 return py3compat.bytes_to_str(out), py3compat.bytes_to_str(err)
147 147
148 148
149 149 def arg_split(s, posix=False, strict=True):
150 150 """Split a command line's arguments in a shell-like manner.
151 151
152 152 This is a modified version of the standard library's shlex.split()
153 153 function, but with a default of posix=False for splitting, so that quotes
154 154 in inputs are respected.
155 155
156 156 if strict=False, then any errors shlex.split would raise will result in the
157 157 unparsed remainder being the last element of the list, rather than raising.
158 158 This is because we sometimes use arg_split to parse things other than
159 159 command-line args.
160 160 """
161 161
162 162 # Unfortunately, python's shlex module is buggy with unicode input:
163 163 # http://bugs.python.org/issue1170
164 164 # At least encoding the input when it's unicode seems to help, but there
165 165 # may be more problems lurking. Apparently this is fixed in python3.
166 166 is_unicode = False
167 167 if (not py3compat.PY3) and isinstance(s, unicode):
168 168 is_unicode = True
169 169 s = s.encode('utf-8')
170 170 lex = shlex.shlex(s, posix=posix)
171 171 lex.whitespace_split = True
172 172 # Extract tokens, ensuring that things like leaving open quotes
173 173 # does not cause this to raise. This is important, because we
174 174 # sometimes pass Python source through this (e.g. %timeit f(" ")),
175 175 # and it shouldn't raise an exception.
176 176 # It may be a bad idea to parse things that are not command-line args
177 177 # through this function, but we do, so let's be safe about it.
178 lex.commenters='' #fix for GH-1269
178 179 tokens = []
179 180 while True:
180 181 try:
181 182 tokens.append(lex.next())
182 183 except StopIteration:
183 184 break
184 185 except ValueError:
185 186 if strict:
186 187 raise
187 188 # couldn't parse, get remaining blob as last token
188 189 tokens.append(lex.token)
189 190 break
190 191
191 192 if is_unicode:
192 193 # Convert the tokens back to unicode.
193 194 tokens = [x.decode('utf-8') for x in tokens]
194 195 return tokens
General Comments 0
You need to be logged in to leave comments. Login now