Index: subprocess2.py |
diff --git a/subprocess2.py b/subprocess2.py |
index afe5c75c17122b289c1a36acf1c8ddeeb3d28ca3..3b48137988c3b2c529520940f0975d5a7ef7dbf3 100644 |
--- a/subprocess2.py |
+++ b/subprocess2.py |
@@ -131,11 +131,9 @@ def get_english_env(env): |
return env |
-def Popen(args, **kwargs): |
+class Popen(subprocess.Popen): |
"""Wraps subprocess.Popen() with various workarounds. |
- Returns a subprocess.Popen object. |
- |
- Forces English output since it's easier to parse the stdout if it is always |
in English. |
- Sets shell=True on windows by default. You can override this by forcing |
@@ -145,57 +143,60 @@ def Popen(args, **kwargs): |
Note: Popen() can throw OSError when cwd or args[0] doesn't exist. Translate |
exceptions generated by cygwin when it fails trying to emulate fork(). |
""" |
- # Make sure we hack subprocess if necessary. |
- hack_subprocess() |
- add_kill() |
- |
- env = get_english_env(kwargs.get('env')) |
- if env: |
- kwargs['env'] = env |
- if kwargs.get('shell') is None: |
- # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for the |
- # executable, but shell=True makes subprocess on Linux fail when it's called |
- # with a list because it only tries to execute the first item in the list. |
- kwargs['shell'] = bool(sys.platform=='win32') |
- |
- if isinstance(args, basestring): |
- tmp_str = args |
- elif isinstance(args, (list, tuple)): |
- tmp_str = ' '.join(args) |
- else: |
- raise CalledProcessError(None, args, kwargs.get('cwd'), None, None) |
- if kwargs.get('cwd', None): |
- tmp_str += '; cwd=%s' % kwargs['cwd'] |
- logging.debug(tmp_str) |
- |
- def fix(stream): |
- if kwargs.get(stream) in (VOID, os.devnull): |
- # Replaces VOID with handle to /dev/null. |
- # Create a temporary file to workaround python's deadlock. |
- # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait |
- # When the pipe fills up, it will deadlock this process. Using a real file |
- # works around that issue. |
- kwargs[stream] = open(os.devnull, 'w') |
- |
- fix('stdout') |
- fix('stderr') |
- |
- try: |
- return subprocess.Popen(args, **kwargs) |
- except OSError, e: |
- if e.errno == errno.EAGAIN and sys.platform == 'cygwin': |
- # Convert fork() emulation failure into a CygwinRebaseError(). |
- raise CygwinRebaseError( |
- e.errno, |
- args, |
- kwargs.get('cwd'), |
- None, |
- 'Visit ' |
- 'http://code.google.com/p/chromium/wiki/CygwinDllRemappingFailure to ' |
- 'learn how to fix this error; you need to rebase your cygwin dlls') |
- # Popen() can throw OSError when cwd or args[0] doesn't exist. Let it go |
- # through |
- raise |
+ def __init__(self, args, **kwargs): |
+ # Make sure we hack subprocess if necessary. |
+ hack_subprocess() |
+ add_kill() |
+ |
+ env = get_english_env(kwargs.get('env')) |
+ if env: |
+ kwargs['env'] = env |
+ if kwargs.get('shell') is None: |
+ # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for |
+ # the executable, but shell=True makes subprocess on Linux fail when it's |
+ # called with a list because it only tries to execute the first item in |
+ # the list. |
+ kwargs['shell'] = bool(sys.platform=='win32') |
+ |
+ if isinstance(args, basestring): |
+ tmp_str = args |
+ elif isinstance(args, (list, tuple)): |
+ tmp_str = ' '.join(args) |
+ else: |
+ raise CalledProcessError(None, args, kwargs.get('cwd'), None, None) |
+ if kwargs.get('cwd', None): |
+ tmp_str += '; cwd=%s' % kwargs['cwd'] |
+ logging.debug(tmp_str) |
+ |
+ def fix(stream): |
+ if kwargs.get(stream) in (VOID, os.devnull): |
+ # Replaces VOID with handle to /dev/null. |
+ # Create a temporary file to workaround python's deadlock. |
+ # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait |
+ # When the pipe fills up, it will deadlock this process. Using a real |
+ # file works around that issue. |
+ kwargs[stream] = open(os.devnull, 'w') |
+ |
+ fix('stdout') |
+ fix('stderr') |
+ |
+ try: |
+ super(Popen, self).__init__(args, **kwargs) |
+ except OSError, e: |
+ if e.errno == errno.EAGAIN and sys.platform == 'cygwin': |
+ # Convert fork() emulation failure into a CygwinRebaseError(). |
+ raise CygwinRebaseError( |
+ e.errno, |
+ args, |
+ kwargs.get('cwd'), |
+ None, |
+ 'Visit ' |
+ 'http://code.google.com/p/chromium/wiki/CygwinDllRemappingFailure ' |
+ 'to learn how to fix this error; you need to rebase your cygwin ' |
+ 'dlls') |
+ # Popen() can throw OSError when cwd or args[0] doesn't exist. Let it go |
+ # through |
+ raise |
def communicate(args, timeout=None, **kwargs): |