Bug 1257516 - Allow the log_handle given to the virtualenv manager to be a file-like object. r=ted
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 25 Mar 2016 16:09:35 +0900
changeset 290975 450ffa461818bdc9eb0763216ea27efc3d311504
parent 290974 7fc90e8065458a180533e08d85fd4c4086220056
child 290976 2a6f03d3e6d446601bffcf88de57b649e5b41c90
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1257516
milestone48.0a1
Bug 1257516 - Allow the log_handle given to the virtualenv manager to be a file-like object. r=ted subprocess functions doesn't directly take file-like objects, so add a minimalistic wrapper to do the right thing instead of subprocess.call when given a file-like object.
python/mozbuild/mozbuild/virtualenv.py
--- a/python/mozbuild/mozbuild/virtualenv.py
+++ b/python/mozbuild/mozbuild/virtualenv.py
@@ -157,16 +157,29 @@ class VirtualenvManager(object):
 
         This should be the main API used from this class as it is the
         highest-level.
         """
         if self.up_to_date(python):
             return self.virtualenv_root
         return self.build(python)
 
+    def _log_process_output(self, *args, **kwargs):
+        if hasattr(self.log_handle, 'fileno'):
+            return subprocess.call(*args, stdout=self.log_handle,
+                                   stderr=subprocess.STDOUT, **kwargs)
+
+        proc = subprocess.Popen(*args, stdout=subprocess.PIPE,
+                                stderr=subprocess.STDOUT, **kwargs)
+
+        for line in proc.stdout:
+            self.log_handle.write(line)
+
+        return proc.wait()
+
     def create(self, python=sys.executable):
         """Create a new, empty virtualenv.
 
         Receives the path to virtualenv's virtualenv.py script (which will be
         called out to), the path to create the virtualenv in, and a handle to
         write output to.
         """
         env = dict(os.environ)
@@ -175,18 +188,17 @@ class VirtualenvManager(object):
         args = [python, self.virtualenv_script_path,
             # Without this, virtualenv.py may attempt to contact the outside
             # world and search for or download a newer version of pip,
             # setuptools, or wheel. This is bad for security, reproducibility,
             # and speed.
             '--no-download',
             self.virtualenv_root]
 
-        result = subprocess.call(args, stdout=self.log_handle,
-            stderr=subprocess.STDOUT, env=env)
+        result = self._log_process_output(args, env=env)
 
         if result:
             raise Exception(
                 'Failed to create virtualenv: %s' % self.virtualenv_root)
 
         self.write_exe_info(python)
 
         return self.virtualenv_root
@@ -424,18 +436,17 @@ class VirtualenvManager(object):
         self.create(python)
 
         # We need to populate the virtualenv using the Python executable in
         # the virtualenv for paths to be proper.
 
         args = [self.python_path, __file__, 'populate', self.topsrcdir,
             self.topobjdir, self.virtualenv_root, self.manifest_path]
 
-        result = subprocess.call(args, stdout=self.log_handle,
-            stderr=subprocess.STDOUT, cwd=self.topsrcdir)
+        result = self._log_process_output(args, cwd=self.topsrcdir)
 
         if result != 0:
             raise Exception('Error populating virtualenv.')
 
         os.utime(self.activate_path, None)
 
         return self.virtualenv_root