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

Side by Side Diff: subprocess2.py

Issue 6706022: Update docstrings and add VOID support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 9 years, 8 months 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/local_rietveld.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
11 import logging 11 import logging
12 import os 12 import os
13 import subprocess 13 import subprocess
14 import sys 14 import sys
15 import tempfile 15 import tempfile
16 import time 16 import time
17 import threading 17 import threading
18 18
19 # Constants forwarded from subprocess. 19 # Constants forwarded from subprocess.
20 PIPE = subprocess.PIPE 20 PIPE = subprocess.PIPE
21 STDOUT = subprocess.STDOUT 21 STDOUT = subprocess.STDOUT
22 # Sends stdout or stderr to os.devnull.
23 VOID = '/dev/null'
24
22 25
23 # Globals. 26 # Globals.
24 # Set to True if you somehow need to disable this hack. 27 # Set to True if you somehow need to disable this hack.
25 SUBPROCESS_CLEANUP_HACKED = False 28 SUBPROCESS_CLEANUP_HACKED = False
26 29
27 30
28 class CalledProcessError(subprocess.CalledProcessError): 31 class CalledProcessError(subprocess.CalledProcessError):
29 """Augment the standard exception with more data.""" 32 """Augment the standard exception with more data."""
30 def __init__(self, returncode, cmd, cwd, stdout, stderr): 33 def __init__(self, returncode, cmd, cwd, stdout, stderr):
31 super(CalledProcessError, self).__init__(returncode, cmd) 34 super(CalledProcessError, self).__init__(returncode, cmd)
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 if not is_english(name): 119 if not is_english(name):
117 env[name] = 'en_US.UTF-8' 120 env[name] = 'en_US.UTF-8'
118 fix_lang('LANG') 121 fix_lang('LANG')
119 fix_lang('LANGUAGE') 122 fix_lang('LANGUAGE')
120 return env 123 return env
121 124
122 125
123 def Popen(args, **kwargs): 126 def Popen(args, **kwargs):
124 """Wraps subprocess.Popen(). 127 """Wraps subprocess.Popen().
125 128
126 Forces English output since it's easier to parse the stdout if it is always in 129 Returns a subprocess.Popen object.
127 English.
128 130
129 Sets shell=True on windows by default. You can override this by forcing shell 131 - Forces English output since it's easier to parse the stdout if it is always
130 parameter to a value. 132 in English.
133 - Sets shell=True on windows by default. You can override this by forcing
134 shell parameter to a value.
135 - Adds support for VOID to not buffer when not needed.
131 136
132 Popen() can throw OSError when cwd or args[0] doesn't exist. 137 Note: Popen() can throw OSError when cwd or args[0] doesn't exist.
133 """ 138 """
134 # Make sure we hack subprocess if necessary. 139 # Make sure we hack subprocess if necessary.
135 hack_subprocess() 140 hack_subprocess()
136 add_kill() 141 add_kill()
137 142
138 env = get_english_env(kwargs.get('env')) 143 env = get_english_env(kwargs.get('env'))
139 if env: 144 if env:
140 kwargs['env'] = env 145 kwargs['env'] = env
141 146
142 if not kwargs.get('shell') is None: 147 if not kwargs.get('shell') is None:
143 # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for the 148 # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for the
144 # executable, but shell=True makes subprocess on Linux fail when it's called 149 # executable, but shell=True makes subprocess on Linux fail when it's called
145 # with a list because it only tries to execute the first item in the list. 150 # with a list because it only tries to execute the first item in the list.
146 kwargs['shell'] = (sys.platform=='win32') 151 kwargs['shell'] = (sys.platform=='win32')
147 152
148 tmp_str = ' '.join(args) 153 tmp_str = ' '.join(args)
149 if kwargs.get('cwd', None): 154 if kwargs.get('cwd', None):
150 tmp_str += '; cwd=%s' % kwargs['cwd'] 155 tmp_str += '; cwd=%s' % kwargs['cwd']
151 logging.debug(tmp_str) 156 logging.debug(tmp_str)
157
158 # Replaces VOID with handle to /dev/null.
159 if kwargs.get('stdout') in (VOID, os.devnull):
160 kwargs['stdout'] = open(os.devnull, 'w')
161 if kwargs.get('stderr') in (VOID, os.devnull):
162 kwargs['stderr'] = open(os.devnull, 'w')
152 return subprocess.Popen(args, **kwargs) 163 return subprocess.Popen(args, **kwargs)
153 164
154 165
155 def call(args, timeout=None, **kwargs): 166 def call(args, timeout=None, **kwargs):
156 """Wraps subprocess.Popen().communicate(). 167 """Wraps subprocess.Popen().communicate().
157 168
158 The process will be kill with error code -9 after |timeout| seconds if set. 169 Returns ((stdout, stderr), returncode).
159 170
160 Automatically passes stdin content as input so do not specify stdin=PIPE. 171 - The process will be kill with error code -9 after |timeout| seconds if set.
161 172 - Automatically passes stdin content as input so do not specify stdin=PIPE.
162 Returns both communicate() tuple and return code wrapped in a tuple.
163 """ 173 """
164 stdin = kwargs.pop('stdin', None) 174 stdin = kwargs.pop('stdin', None)
165 if stdin is not None: 175 if stdin is not None:
166 assert stdin != PIPE 176 assert stdin != PIPE
167 # When stdin is passed as an argument, use it as the actual input data and 177 # When stdin is passed as an argument, use it as the actual input data and
168 # set the Popen() parameter accordingly. 178 # set the Popen() parameter accordingly.
169 kwargs['stdin'] = PIPE 179 kwargs['stdin'] = PIPE
170 180
171 if not timeout: 181 if not timeout:
172 # Normal workflow. 182 # Normal workflow.
(...skipping 24 matching lines...) Expand all
197 # or look at call()[1] == -9. 207 # or look at call()[1] == -9.
198 proc.returncode = -9 208 proc.returncode = -9
199 time.sleep(0.001) 209 time.sleep(0.001)
200 # Now that the process died, reset the cursor and read the file. 210 # Now that the process died, reset the cursor and read the file.
201 buff.seek(0) 211 buff.seek(0)
202 out = [buff.read(), None] 212 out = [buff.read(), None]
203 return out, proc.returncode 213 return out, proc.returncode
204 214
205 215
206 def check_call(args, **kwargs): 216 def check_call(args, **kwargs):
207 """Similar to subprocess.check_call() but use call() instead. 217 """Improved version of subprocess.check_call().
208 218
209 This permits to include more details in CalledProcessError(). 219 Returns (stdout, stderr), unlike subprocess.check_call().
210
211 Runs a command and throws an exception if the command failed.
212
213 Returns communicate() tuple.
214 """ 220 """
215 out, returncode = call(args, **kwargs) 221 out, returncode = call(args, **kwargs)
216 if returncode: 222 if returncode:
217 raise CalledProcessError( 223 raise CalledProcessError(
218 returncode, args, kwargs.get('cwd'), out[0], out[1]) 224 returncode, args, kwargs.get('cwd'), out[0], out[1])
219 return out 225 return out
220 226
221 227
222 def capture(args, **kwargs): 228 def capture(args, **kwargs):
223 """Captures stdout of a process call and returns it. 229 """Captures stdout of a process call and returns it.
224 230
225 Similar to check_output() excepts that it discards return code. 231 Returns stdout.
226 232
227 Discards communicate()[1]. By default sets stderr=STDOUT. 233 - Discards returncode.
234 - Discards stderr. By default sets stderr=STDOUT.
228 """ 235 """
229 if kwargs.get('stderr') is None: 236 if kwargs.get('stderr') is None:
230 kwargs['stderr'] = STDOUT 237 kwargs['stderr'] = STDOUT
231 return call(args, stdout=PIPE, **kwargs)[0][0] 238 return call(args, stdout=PIPE, **kwargs)[0][0]
232 239
233 240
234 def check_output(args, **kwargs): 241 def check_output(args, **kwargs):
235 """Captures stdout of a process call and returns it. 242 """Captures stdout of a process call and returns it.
236 243
237 Discards communicate()[1]. By default sets stderr=STDOUT. 244 Returns stdout.
238 245
239 Throws if return code is not 0. 246 - Discards stderr. By default sets stderr=STDOUT.
240 247 - Throws if return code is not 0.
241 Works even prior to python 2.7. 248 - Works even prior to python 2.7.
242 """ 249 """
243 if kwargs.get('stderr') is None: 250 if kwargs.get('stderr') is None:
244 kwargs['stderr'] = STDOUT 251 kwargs['stderr'] = STDOUT
245 return check_call(args, stdout=PIPE, **kwargs)[0] 252 return check_call(args, stdout=PIPE, **kwargs)[0]
OLDNEW
« no previous file with comments | « no previous file | tests/local_rietveld.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698