Title: [217801] trunk/Tools
Revision
217801
Author
[email protected]
Date
2017-06-05 16:01:21 -0700 (Mon, 05 Jun 2017)

Log Message

webkitpy: Abstract Executive class
https://bugs.webkit.org/show_bug.cgi?id=172928
<rdar://problem/32569531>

Reviewed by Ryosuke Niwa.

Adds an AbstractExecutive class and makes Executive extend AbstractExecutive.
This will make it straightforward to create additional derived classes that
adhere to the same interface, say for iOS on-device testing.

* Scripts/webkitpy/common/system/abstractexecutive.py: Added.
(AbstractExecutive):
(AbstractExecutive.run_and_throw_if_fail):
(AbstractExecutive.cpu_count):
(AbstractExecutive.interpreter_for_script):
(AbstractExecutive.shell_command_for_script):
(AbstractExecutive.kill_process):
(AbstractExecutive.check_running_pid):
(AbstractExecutive.running_pids):
(AbstractExecutive.wait_newest):
(AbstractExecutive.wait_limited):
(AbstractExecutive.interrupt):
(AbstractExecutive.default_error_handler):
(AbstractExecutive.ignore_error):
(AbstractExecutive._stringify_args):
(AbstractExecutive.command_for_printing):
(AbstractExecutive.run_command):
(AbstractExecutive.popen):
(AbstractExecutive.run_in_parallel):
* Scripts/webkitpy/common/system/executive.py:
(Executive):
(Executive.cpu_count):
(Executive.running_pids):
(Executive.kill_all):
(Executive._compute_stdin):
(Executive.interpreter_for_script): Deleted.
(Executive.shell_command_for_script): Deleted.
(Executive.wait_newest): Deleted.
(Executive.wait_limited): Deleted.
(Executive.default_error_handler): Deleted.
(Executive.ignore_error): Deleted.
(Executive.command_for_printing): Deleted.

Modified Paths

Added Paths

Diff

Modified: trunk/Tools/ChangeLog (217800 => 217801)


--- trunk/Tools/ChangeLog	2017-06-05 22:41:42 UTC (rev 217800)
+++ trunk/Tools/ChangeLog	2017-06-05 23:01:21 UTC (rev 217801)
@@ -1,3 +1,48 @@
+2017-06-05  Daniel Bates  <[email protected]>
+
+        webkitpy: Abstract Executive class
+        https://bugs.webkit.org/show_bug.cgi?id=172928
+        <rdar://problem/32569531>
+
+        Reviewed by Ryosuke Niwa.
+
+        Adds an AbstractExecutive class and makes Executive extend AbstractExecutive.
+        This will make it straightforward to create additional derived classes that
+        adhere to the same interface, say for iOS on-device testing.
+
+        * Scripts/webkitpy/common/system/abstractexecutive.py: Added.
+        (AbstractExecutive):
+        (AbstractExecutive.run_and_throw_if_fail):
+        (AbstractExecutive.cpu_count):
+        (AbstractExecutive.interpreter_for_script):
+        (AbstractExecutive.shell_command_for_script):
+        (AbstractExecutive.kill_process):
+        (AbstractExecutive.check_running_pid):
+        (AbstractExecutive.running_pids):
+        (AbstractExecutive.wait_newest):
+        (AbstractExecutive.wait_limited):
+        (AbstractExecutive.interrupt):
+        (AbstractExecutive.default_error_handler):
+        (AbstractExecutive.ignore_error):
+        (AbstractExecutive._stringify_args):
+        (AbstractExecutive.command_for_printing):
+        (AbstractExecutive.run_command):
+        (AbstractExecutive.popen):
+        (AbstractExecutive.run_in_parallel):
+        * Scripts/webkitpy/common/system/executive.py:
+        (Executive):
+        (Executive.cpu_count):
+        (Executive.running_pids):
+        (Executive.kill_all):
+        (Executive._compute_stdin):
+        (Executive.interpreter_for_script): Deleted.
+        (Executive.shell_command_for_script): Deleted.
+        (Executive.wait_newest): Deleted.
+        (Executive.wait_limited): Deleted.
+        (Executive.default_error_handler): Deleted.
+        (Executive.ignore_error): Deleted.
+        (Executive.command_for_printing): Deleted.
+
 2017-06-05  Jonathan Bedard  <[email protected]>
 
         webkitpy: Add iOS to platform

Added: trunk/Tools/Scripts/webkitpy/common/system/abstractexecutive.py (0 => 217801)


--- trunk/Tools/Scripts/webkitpy/common/system/abstractexecutive.py	                        (rev 0)
+++ trunk/Tools/Scripts/webkitpy/common/system/abstractexecutive.py	2017-06-05 23:01:21 UTC (rev 217801)
@@ -0,0 +1,127 @@
+# Copyright (C) 2017 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import sys
+import time
+
+from webkitpy.common.system.filesystem import FileSystem
+
+
+class AbstractExecutive(object):
+
+    def run_and_throw_if_fail(self, args, quiet=False, decode_output=True, **kwargs):
+        raise NotImplementedError('subclasses must implement')
+
+    def cpu_count(self):
+        raise NotImplementedError('subclasses must implement')
+
+    @staticmethod
+    def interpreter_for_script(script_path, fs=None):
+        fs = fs or FileSystem()
+        lines = fs.read_text_file(script_path).splitlines()
+        if not len(lines):
+            return None
+        first_line = lines[0]
+        if not first_line.startswith('#!'):
+            return None
+        if first_line.find('python') > -1:
+            return sys.executable
+        if first_line.find('perl') > -1:
+            return 'perl'
+        if first_line.find('ruby') > -1:
+            return 'ruby'
+        return None
+
+    @staticmethod
+    def shell_command_for_script(script_path, fs=None):
+        fs = fs or FileSystem()
+        # Win32 does not support shebang. We need to detect the interpreter ourself.
+        if sys.platform.startswith('win'):
+            interpreter = AbstractExecutive.interpreter_for_script(script_path, fs)
+            if interpreter:
+                return [interpreter, script_path]
+        return [script_path]
+
+    def kill_process(self, pid):
+        raise NotImplementedError('subclasses must implement')
+
+    def check_running_pid(self, pid):
+        raise NotImplementedError('subclasses must implement')
+
+    def running_pids(self, process_name_filter=None):
+        raise NotImplementedError('subclasses must implement')
+
+    def wait_newest(self, process_name_filter=None):
+        if not process_name_filter:
+            process_name_filter = lambda process_name: True
+
+        running_pids = self.running_pids(process_name_filter)
+        if not running_pids:
+            return
+        pid = running_pids[-1]
+
+        while self.check_running_pid(pid):
+            time.sleep(0.25)
+
+    def wait_limited(self, pid, limit_in_seconds=None, check_frequency_in_seconds=None):
+        seconds_left = limit_in_seconds or 10
+        sleep_length = check_frequency_in_seconds or 1
+        while seconds_left > 0 and self.check_running_pid(pid):
+            seconds_left -= sleep_length
+            time.sleep(sleep_length)
+
+    def interrupt(self, pid):
+        raise NotImplementedError('subclasses must implement')
+
+    @staticmethod
+    def default_error_handler(error):
+        raise error
+
+    @staticmethod
+    def ignore_error(error):
+        pass
+
+    def _stringify_args(self, args):
+        return map(unicode, args)
+
+    def command_for_printing(self, args):
+        """Returns a print-ready string representing command args.
+        The string should be copy/paste ready for execution in a shell."""
+        args = self._stringify_args(args)
+        escaped_args = []
+        for arg in args:
+            if isinstance(arg, unicode):
+                # Escape any non-ascii characters for easy copy/paste
+                arg = arg.encode("unicode_escape")
+            # FIXME: Do we need to fix quotes here?
+            escaped_args.append(arg)
+        return " ".join(escaped_args)
+
+    def run_command(self, args, cwd=None, env=None, input=None, error_handler=None,
+        return_exit_code=False, return_stderr=True, decode_output=True):
+        raise NotImplementedError('subclasses must implement')
+
+    def popen(self, args, **kwargs):
+        raise NotImplementedError('subclasses must implement')
+
+    def run_in_parallel(self, command_lines_and_cwds, processes=None):
+        raise NotImplementedError('subclasses must implement')

Modified: trunk/Tools/Scripts/webkitpy/common/system/executive.py (217800 => 217801)


--- trunk/Tools/Scripts/webkitpy/common/system/executive.py	2017-06-05 22:41:42 UTC (rev 217800)
+++ trunk/Tools/Scripts/webkitpy/common/system/executive.py	2017-06-05 23:01:21 UTC (rev 217801)
@@ -37,8 +37,8 @@
 import sys
 import time
 
+from webkitpy.common.system.abstractexecutive import AbstractExecutive
 from webkitpy.common.system.outputtee import Tee
-from webkitpy.common.system.filesystem import FileSystem
 
 
 _log = logging.getLogger(__name__)
@@ -80,7 +80,7 @@
         return os.path.basename(command_path)
 
 
-class Executive(object):
+class Executive(AbstractExecutive):
     PIPE = subprocess.PIPE
     STDOUT = subprocess.STDOUT
 
@@ -157,33 +157,6 @@
             pass
         return multiprocessing.cpu_count()
 
-    @staticmethod
-    def interpreter_for_script(script_path, fs=None):
-        fs = fs or FileSystem()
-        lines = fs.read_text_file(script_path).splitlines()
-        if not len(lines):
-            return None
-        first_line = lines[0]
-        if not first_line.startswith('#!'):
-            return None
-        if first_line.find('python') > -1:
-            return sys.executable
-        if first_line.find('perl') > -1:
-            return 'perl'
-        if first_line.find('ruby') > -1:
-            return 'ruby'
-        return None
-
-    @staticmethod
-    def shell_command_for_script(script_path, fs=None):
-        fs = fs or FileSystem()
-        # Win32 does not support shebang. We need to detect the interpreter ourself.
-        if sys.platform.startswith('win'):
-            interpreter = Executive.interpreter_for_script(script_path, fs)
-            if interpreter:
-                return [interpreter, script_path]
-        return [script_path]
-
     def kill_process(self, pid):
         # Killing a process with a pid of 0 or a negative pid is a valid command, but
         # will kill all processes in this process' group (if 0) or all non-system processes
@@ -323,25 +296,6 @@
 
         return sorted(running_pids)
 
-    def wait_newest(self, process_name_filter=None):
-        if not process_name_filter:
-            process_name_filter = lambda process_name: True
-
-        running_pids = self.running_pids(process_name_filter)
-        if not running_pids:
-            return
-        pid = running_pids[-1]
-
-        while self.check_running_pid(pid):
-            time.sleep(0.25)
-
-    def wait_limited(self, pid, limit_in_seconds=None, check_frequency_in_seconds=None):
-        seconds_left = limit_in_seconds or 10
-        sleep_length = check_frequency_in_seconds or 1
-        while seconds_left > 0 and self.check_running_pid(pid):
-            seconds_left -= sleep_length
-            time.sleep(sleep_length)
-
     def _windows_image_name(self, process_name):
         name, extension = os.path.splitext(process_name)
         if not extension:
@@ -384,17 +338,6 @@
         # We should log in exit_code == 1
         self.run_command(command, error_handler=self.ignore_error)
 
-    # Error handlers do not need to be static methods once all callers are
-    # updated to use an Executive object.
-
-    @staticmethod
-    def default_error_handler(error):
-        raise error
-
-    @staticmethod
-    def ignore_error(error):
-        pass
-
     def _compute_stdin(self, input):
         """Returns (stdin, string_to_communicate)"""
         # FIXME: We should be returning /dev/null for stdin
@@ -414,19 +357,6 @@
             input = input.encode(self._child_process_encoding())
         return (self.PIPE, input)
 
-    def command_for_printing(self, args):
-        """Returns a print-ready string representing command args.
-        The string should be copy/paste ready for execution in a shell."""
-        args = self._stringify_args(args)
-        escaped_args = []
-        for arg in args:
-            if isinstance(arg, unicode):
-                # Escape any non-ascii characters for easy copy/paste
-                arg = arg.encode("unicode_escape")
-            # FIXME: Do we need to fix quotes here?
-            escaped_args.append(arg)
-        return " ".join(escaped_args)
-
     # FIXME: run_and_throw_if_fail should be merged into this method.
     def run_command(self,
                     args,
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to