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

Side by Side Diff: subprocess2.py

Issue 8570005: Make subprocess2.Popen a class instead of a function. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 9 years, 1 month 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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 # Requires modifications. 124 # Requires modifications.
125 env = env.copy() 125 env = env.copy()
126 def fix_lang(name): 126 def fix_lang(name):
127 if not is_english(name): 127 if not is_english(name):
128 env[name] = 'en_US.UTF-8' 128 env[name] = 'en_US.UTF-8'
129 fix_lang('LANG') 129 fix_lang('LANG')
130 fix_lang('LANGUAGE') 130 fix_lang('LANGUAGE')
131 return env 131 return env
132 132
133 133
134 def Popen(args, **kwargs): 134 class Popen(subprocess.Popen):
135 """Wraps subprocess.Popen() with various workarounds. 135 """Wraps subprocess.Popen() with various workarounds.
136 136
137 Returns a subprocess.Popen object.
138
139 - 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
140 in English. 138 in English.
141 - 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
142 shell parameter to a value. 140 shell parameter to a value.
143 - Adds support for VOID to not buffer when not needed. 141 - Adds support for VOID to not buffer when not needed.
144 142
145 Note: Popen() can throw OSError when cwd or args[0] doesn't exist. Translate 143 Note: Popen() can throw OSError when cwd or args[0] doesn't exist. Translate
146 exceptions generated by cygwin when it fails trying to emulate fork(). 144 exceptions generated by cygwin when it fails trying to emulate fork().
147 """ 145 """
148 # Make sure we hack subprocess if necessary. 146 def __init__(self, args, **kwargs):
149 hack_subprocess() 147 # Make sure we hack subprocess if necessary.
150 add_kill() 148 hack_subprocess()
149 add_kill()
151 150
152 env = get_english_env(kwargs.get('env')) 151 env = get_english_env(kwargs.get('env'))
153 if env: 152 if env:
154 kwargs['env'] = env 153 kwargs['env'] = env
155 if kwargs.get('shell') is None: 154 if kwargs.get('shell') is None:
156 # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for the 155 # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for
157 # executable, but shell=True makes subprocess on Linux fail when it's called 156 # the executable, but shell=True makes subprocess on Linux fail when it's
158 # with a list because it only tries to execute the first item in the list. 157 # called with a list because it only tries to execute the first item in
159 kwargs['shell'] = bool(sys.platform=='win32') 158 # the list.
159 kwargs['shell'] = bool(sys.platform=='win32')
160 160
161 if isinstance(args, basestring): 161 if isinstance(args, basestring):
162 tmp_str = args 162 tmp_str = args
163 elif isinstance(args, (list, tuple)): 163 elif isinstance(args, (list, tuple)):
164 tmp_str = ' '.join(args) 164 tmp_str = ' '.join(args)
165 else: 165 else:
166 raise CalledProcessError(None, args, kwargs.get('cwd'), None, None) 166 raise CalledProcessError(None, args, kwargs.get('cwd'), None, None)
167 if kwargs.get('cwd', None): 167 if kwargs.get('cwd', None):
168 tmp_str += '; cwd=%s' % kwargs['cwd'] 168 tmp_str += '; cwd=%s' % kwargs['cwd']
169 logging.debug(tmp_str) 169 logging.debug(tmp_str)
170 170
171 def fix(stream): 171 def fix(stream):
172 if kwargs.get(stream) in (VOID, os.devnull): 172 if kwargs.get(stream) in (VOID, os.devnull):
173 # Replaces VOID with handle to /dev/null. 173 # Replaces VOID with handle to /dev/null.
174 # Create a temporary file to workaround python's deadlock. 174 # Create a temporary file to workaround python's deadlock.
175 # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait 175 # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait
176 # When the pipe fills up, it will deadlock this process. Using a real file 176 # When the pipe fills up, it will deadlock this process. Using a real
177 # works around that issue. 177 # file works around that issue.
178 kwargs[stream] = open(os.devnull, 'w') 178 kwargs[stream] = open(os.devnull, 'w')
179 179
180 fix('stdout') 180 fix('stdout')
181 fix('stderr') 181 fix('stderr')
182 182
183 try: 183 try:
184 return subprocess.Popen(args, **kwargs) 184 super(Popen, self).__init__(args, **kwargs)
185 except OSError, e: 185 except OSError, e:
186 if e.errno == errno.EAGAIN and sys.platform == 'cygwin': 186 if e.errno == errno.EAGAIN and sys.platform == 'cygwin':
187 # Convert fork() emulation failure into a CygwinRebaseError(). 187 # Convert fork() emulation failure into a CygwinRebaseError().
188 raise CygwinRebaseError( 188 raise CygwinRebaseError(
189 e.errno, 189 e.errno,
190 args, 190 args,
191 kwargs.get('cwd'), 191 kwargs.get('cwd'),
192 None, 192 None,
193 'Visit ' 193 'Visit '
194 'http://code.google.com/p/chromium/wiki/CygwinDllRemappingFailure to ' 194 'http://code.google.com/p/chromium/wiki/CygwinDllRemappingFailure '
195 'learn how to fix this error; you need to rebase your cygwin dlls') 195 'to learn how to fix this error; you need to rebase your cygwin '
196 # Popen() can throw OSError when cwd or args[0] doesn't exist. Let it go 196 'dlls')
197 # through 197 # Popen() can throw OSError when cwd or args[0] doesn't exist. Let it go
198 raise 198 # through
199 raise
199 200
200 201
201 def communicate(args, timeout=None, **kwargs): 202 def communicate(args, timeout=None, **kwargs):
202 """Wraps subprocess.Popen().communicate(). 203 """Wraps subprocess.Popen().communicate().
203 204
204 Returns ((stdout, stderr), returncode). 205 Returns ((stdout, stderr), returncode).
205 206
206 - The process will be killed after |timeout| seconds and returncode set to 207 - The process will be killed after |timeout| seconds and returncode set to
207 TIMED_OUT. 208 TIMED_OUT.
208 - Automatically passes stdin content as input so do not specify stdin=PIPE. 209 - Automatically passes stdin content as input so do not specify stdin=PIPE.
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 302
302 Captures stdout of a process call and returns stdout only. 303 Captures stdout of a process call and returns stdout only.
303 304
304 - Throws if return code is not 0. 305 - Throws if return code is not 0.
305 - Works even prior to python 2.7. 306 - Works even prior to python 2.7.
306 - Blocks stdin by default if not specified since no output will be visible. 307 - Blocks stdin by default if not specified since no output will be visible.
307 - As per doc, "The stdout argument is not allowed as it is used internally." 308 - As per doc, "The stdout argument is not allowed as it is used internally."
308 """ 309 """
309 kwargs.setdefault('stdin', VOID) 310 kwargs.setdefault('stdin', VOID)
310 return check_call_out(args, stdout=PIPE, **kwargs)[0] 311 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