Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Side by Side Diff: subprocess2.py

Issue 8694006: Add Popen.start property. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/subprocess2_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # coding=utf8 1 # coding=utf8
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 """Collection of subprocess wrapper functions. 5 """Collection of subprocess wrapper functions.
6 6
7 In theory you shouldn't need anything else in subprocess, or this module failed. 7 In theory you shouldn't need anything else in subprocess, or this module failed.
8 """ 8 """
9 9
10 from __future__ import with_statement 10 from __future__ import with_statement
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 132
133 133
134 class Popen(subprocess.Popen): 134 class Popen(subprocess.Popen):
135 """Wraps subprocess.Popen() with various workarounds. 135 """Wraps subprocess.Popen() with various workarounds.
136 136
137 - Forces English output since it's easier to parse the stdout if it is always 137 - Forces English output since it's easier to parse the stdout if it is always
138 in English. 138 in English.
139 - Sets shell=True on windows by default. You can override this by forcing 139 - Sets shell=True on windows by default. You can override this by forcing
140 shell parameter to a value. 140 shell parameter to a value.
141 - Adds support for VOID to not buffer when not needed. 141 - Adds support for VOID to not buffer when not needed.
142 - Adds self.start property.
142 143
143 Note: Popen() can throw OSError when cwd or args[0] doesn't exist. Translate 144 Note: Popen() can throw OSError when cwd or args[0] doesn't exist. Translate
144 exceptions generated by cygwin when it fails trying to emulate fork(). 145 exceptions generated by cygwin when it fails trying to emulate fork().
145 """ 146 """
146 def __init__(self, args, **kwargs): 147 def __init__(self, args, **kwargs):
147 # Make sure we hack subprocess if necessary. 148 # Make sure we hack subprocess if necessary.
148 hack_subprocess() 149 hack_subprocess()
149 add_kill() 150 add_kill()
150 151
151 env = get_english_env(kwargs.get('env')) 152 env = get_english_env(kwargs.get('env'))
(...skipping 21 matching lines...) Expand all
173 # Replaces VOID with handle to /dev/null. 174 # Replaces VOID with handle to /dev/null.
174 # Create a temporary file to workaround python's deadlock. 175 # Create a temporary file to workaround python's deadlock.
175 # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait 176 # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait
176 # When the pipe fills up, it will deadlock this process. Using a real 177 # When the pipe fills up, it will deadlock this process. Using a real
177 # file works around that issue. 178 # file works around that issue.
178 kwargs[stream] = open(os.devnull, 'w') 179 kwargs[stream] = open(os.devnull, 'w')
179 180
180 fix('stdout') 181 fix('stdout')
181 fix('stderr') 182 fix('stderr')
182 183
184 self.start = time.time()
185
183 try: 186 try:
184 super(Popen, self).__init__(args, **kwargs) 187 super(Popen, self).__init__(args, **kwargs)
185 except OSError, e: 188 except OSError, e:
186 if e.errno == errno.EAGAIN and sys.platform == 'cygwin': 189 if e.errno == errno.EAGAIN and sys.platform == 'cygwin':
187 # Convert fork() emulation failure into a CygwinRebaseError(). 190 # Convert fork() emulation failure into a CygwinRebaseError().
188 raise CygwinRebaseError( 191 raise CygwinRebaseError(
189 e.errno, 192 e.errno,
190 args, 193 args,
191 kwargs.get('cwd'), 194 kwargs.get('cwd'),
192 None, 195 None,
193 'Visit ' 196 'Visit '
194 'http://code.google.com/p/chromium/wiki/CygwinDllRemappingFailure ' 197 'http://code.google.com/p/chromium/wiki/CygwinDllRemappingFailure '
195 'to learn how to fix this error; you need to rebase your cygwin ' 198 'to learn how to fix this error; you need to rebase your cygwin '
196 'dlls') 199 'dlls')
197 # Popen() can throw OSError when cwd or args[0] doesn't exist. Let it go 200 # Popen() can throw OSError when cwd or args[0] doesn't exist. Let it go
198 # through 201 # through
199 raise 202 raise
200 203
201 204
202 def communicate(args, timeout=None, **kwargs): 205 def communicate(args, timeout=None, **kwargs):
203 """Wraps subprocess.Popen().communicate(). 206 """Wraps subprocess.Popen().communicate() and add timeout support.
204 207
205 Returns ((stdout, stderr), returncode). 208 Returns ((stdout, stderr), returncode).
206 209
207 - The process will be killed after |timeout| seconds and returncode set to 210 - The process will be killed after |timeout| seconds and returncode set to
208 TIMED_OUT. 211 TIMED_OUT.
209 - Automatically passes stdin content as input so do not specify stdin=PIPE. 212 - Automatically passes stdin content as input so do not specify stdin=PIPE.
210 """ 213 """
211 stdin = kwargs.pop('stdin', None) 214 stdin = kwargs.pop('stdin', None)
212 if stdin is not None: 215 if stdin is not None:
213 if stdin is VOID: 216 if stdin is VOID:
(...skipping 11 matching lines...) Expand all
225 if stdin is not None: 228 if stdin is not None:
226 return proc.communicate(stdin), proc.returncode 229 return proc.communicate(stdin), proc.returncode
227 else: 230 else:
228 return proc.communicate(), proc.returncode 231 return proc.communicate(), proc.returncode
229 232
230 # Create a temporary file to workaround python's deadlock. 233 # Create a temporary file to workaround python's deadlock.
231 # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait 234 # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait
232 # When the pipe fills up, it will deadlock this process. Using a real file 235 # When the pipe fills up, it will deadlock this process. Using a real file
233 # works around that issue. 236 # works around that issue.
234 with tempfile.TemporaryFile() as buff: 237 with tempfile.TemporaryFile() as buff:
235 start = time.time()
236 kwargs['stdout'] = buff 238 kwargs['stdout'] = buff
237 proc = Popen(args, **kwargs) 239 proc = Popen(args, **kwargs)
238 if stdin is not None: 240 if stdin is not None:
239 proc.stdin.write(stdin) 241 proc.stdin.write(stdin)
240 while proc.returncode is None: 242 while proc.returncode is None:
241 proc.poll() 243 proc.poll()
242 if timeout and (time.time() - start) > timeout: 244 if timeout and (time.time() - proc.start) > timeout:
243 proc.kill() 245 proc.kill()
244 proc.wait() 246 proc.wait()
245 # It's -9 on linux and 1 on Windows. Standardize to TIMED_OUT. 247 # It's -9 on linux and 1 on Windows. Standardize to TIMED_OUT.
246 proc.returncode = TIMED_OUT 248 proc.returncode = TIMED_OUT
247 time.sleep(0.001) 249 time.sleep(0.001)
248 # Now that the process died, reset the cursor and read the file. 250 # Now that the process died, reset the cursor and read the file.
249 buff.seek(0) 251 buff.seek(0)
250 out = (buff.read(), None) 252 out = (buff.read(), None)
251 return out, proc.returncode 253 return out, proc.returncode
252 254
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 304
303 Captures stdout of a process call and returns stdout only. 305 Captures stdout of a process call and returns stdout only.
304 306
305 - Throws if return code is not 0. 307 - Throws if return code is not 0.
306 - Works even prior to python 2.7. 308 - Works even prior to python 2.7.
307 - Blocks stdin by default if not specified since no output will be visible. 309 - Blocks stdin by default if not specified since no output will be visible.
308 - As per doc, "The stdout argument is not allowed as it is used internally." 310 - As per doc, "The stdout argument is not allowed as it is used internally."
309 """ 311 """
310 kwargs.setdefault('stdin', VOID) 312 kwargs.setdefault('stdin', VOID)
311 return check_call_out(args, stdout=PIPE, **kwargs)[0] 313 return check_call_out(args, stdout=PIPE, **kwargs)[0]
OLDNEW
« no previous file with comments | « no previous file | tests/subprocess2_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698