| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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] |
| OLD | NEW |