Title: [250375] trunk/Tools
Revision
250375
Author
jbed...@apple.com
Date
2019-09-25 19:01:53 -0700 (Wed, 25 Sep 2019)

Log Message

Python 3: Add support in webkitpy.common.system
https://bugs.webkit.org/show_bug.cgi?id=201826
<rdar://problem/55452671>

Reviewed by Stephanie Lewis.

Tested compatibility by running 'python3 -m unittest webkitpy.common.system.<_unittest>' on
each of the effected files.

* Scripts/webkitpy/common/checkout/changelog.py: Import StringIO from io module.
(set_reviewer):
(set_short_description_and_bug_url):
* Scripts/webkitpy/common/checkout/checkout.py:  Import StringIO from io module.
(Checkout._latest_entry_for_changelog_at_revision):
* Scripts/webkitpy/common/config/committers.py:
(CommitterList.load_json): iteritems -> items.
* Scripts/webkitpy/common/net/networktransaction.py:
(NetworkTransaction.run): urllib2 is urllib in Python3.
* Scripts/webkitpy/common/system/abstractexecutive.py:
(AbstractExecutive._stringify_args):
(AbstractExecutive.command_for_printing): The str type is unicode in Python3.
* Scripts/webkitpy/common/system/crashlogs_unittest.py: Explicitly encode and decode binary crashlogs.
* Scripts/webkitpy/common/system/environment_unittest.py: Use absolute imports.
* Scripts/webkitpy/common/system/executive.py:
(ScriptError.message_with_output): The str type is unicode in Python3.
(Executive.WrappedPopen): Python3's Popen object is a context manager. To allow us to use it as one,
our Python2 Popen needs to be one as well.
(Executive.WrappedPopen.__init__):
(Executive.WrappedPopen.__enter__):
(Executive.WrappedPopen.__exit__):
(Executive._run_command_with_teed_output): Simplify loop, decode unicode strings.
(Executive.run_and_throw_if_fail): The child output file should not be unicode strings.
(Executive.running_pids): Use the Popen context manager to guarantee clean-up.
(Executive._compute_stdin):
(Executive.run_command): Use the Popen context manager to guarantee clean-up.
(Executive._stringify_args): The str type is unicode in Python3.
(Executive.popen): Return a context manager if the Popen object is not one.
* Scripts/webkitpy/common/system/executive_mock.py:
(MockProcess.__init__): StringIO -> BytesIO.
(MockProcess.__enter__):
(MockProcess):
(MockProcess.__exit__):
* Scripts/webkitpy/common/system/executive_unittest.py:
(ExecutiveTest.test_auto_stringify_args): Use the Popen context manager to guarantee clean-up.
(ExecutiveTest.test_popen_args): Ditto.
(ExecutiveTest.serial_test_kill_process): Ditto.
(ExecutiveTest.serial_test_kill_all): Ditto.
* Scripts/webkitpy/common/system/filesystem.py:
(FileSystem.read_binary_file): Use 'open' instead of 'file'.
(FileSystem.write_binary_file): Ditto.
(FileSystem.write_text_file): The str type is unicode in Python3.
(FileSystem.relpath):
(FileSystem.remove): The WindowsError is just anther OSError in Python3.
(FileSystem._WindowsError): Deleted.
* Scripts/webkitpy/common/system/filesystem_mock.py:
(MockFileSystem.glob): filter returns a generator instead of a list.
(WritableBinaryFileObject.__init__): Binary files are comprised of bytes, not string in Python3.
(WritableBinaryFileObject.write): Ditto.
(ReadableTextFileObject.__init__): Ditto.
* Scripts/webkitpy/common/system/filesystem_mock_unittest.py:
(MockFileSystemTest.test_normpath):
(MockFileSystemTest.test_dirs_under): assertEquals -> assertEqual.
* Scripts/webkitpy/common/system/filesystem_unittest.py:
(RealFileSystemTest.test_read_and_write_file): Explicitly define byte arrays instead of strings.
(RealFileSystemTest.test_remove_file_with_retry.remove_with_exception): The WindowsError is just
anther OSError in Python3.
* Scripts/webkitpy/common/system/outputcapture.py:
* Scripts/webkitpy/common/system/outputtee_unittest.py:
(SimpleTeeTest.test_simple_tee):
* Scripts/webkitpy/common/system/path.py:
(_escape): urllib library has been broken into parts.
* Scripts/webkitpy/common/system/pemfile.py:
(_parse_pem_format.find_end): Python3 does not define a maxint.
* Scripts/webkitpy/common/system/pemfile_unittest.py:
* Scripts/webkitpy/common/system/platforminfo.py:
(PlatformInfo.total_bytes_memory): Not 'long' type in Python3.
* Scripts/webkitpy/common/system/platforminfo_unittest.py:
(TestPlatformInfo.test_real_code): assertNotEquals -> assertNotEqual.
(TestPlatformInfo.test_display_name): Ditto.
* Scripts/webkitpy/common/system/profiler.py:
(ProfilerFactory.create_profiler): Manually implement ifilter.
* Scripts/webkitpy/common/system/profiler_unittest.py: Use absolute imports.
* Scripts/webkitpy/common/system/stack_utils_unittest.py:
(current_thread_id): items() returns a generator in Python3.
* Scripts/webkitpy/common/system/systemhost.py: Use absolute imports.
* Scripts/webkitpy/common/system/urlfetcher.py: Removed.
* Scripts/webkitpy/common/system/urlfetcher_mock.py: Removed.
* Scripts/webkitpy/common/system/user.py:
(User.prompt): Use absolute imports, raw_input -> input.
(User.prompt_with_multiple_lists):
(User.prompt_with_list):
(User.confirm):
* Scripts/webkitpy/common/unicode.py: Tooling to manage compatibility between Python 2
and Python 3 unicode handling.
* Scripts/webkitpy/common/system/user_mock.py:
(MockUser.prompt): raw_input -> input.
(MockUser.prompt_with_list): Ditto.
* Scripts/webkitpy/common/version.py:
(Version.from_iterable): xrange -> range.
(Version.from_name): Use absolute import path.
(Version.__contains__): xrange -> range.
(Version.__str__): xrange -> range.
(Version.__cmp__): amp is no longer an operator in Python3, but versions are comprised
Of integers, so subtraction has the same effect.
(Version):
(Version.__eq__): __cmp__ operator is no longer respected, so we need to implement
each comparison.
(Version.__ne__): Ditto.
(Version.__lt__): Ditto.
(Version.__le__): Ditto.
(Version.__gt__): Ditto.
(Version.__ge__): Ditto.
* Scripts/webkitpy/common/version_name_map.py:
(VersionNameMap._automap_to_major_version):
(VersionNameMap.to_name): xrange -> range.
(VersionNameMap.from_name): iteritems -> items.
* Scripts/webkitpy/common/version_name_map_unittest.py: Use absolute imports.
* Scripts/webkitpy/common/version_unittest.py: Ditto.
* Scripts/webkitpy/common/wavediff.py:
(WaveDiff.__init__): StringIO -> BytesIO.
* Scripts/webkitpy/port/__init__.py:
(outside):

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Tools/ChangeLog (250374 => 250375)


--- trunk/Tools/ChangeLog	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/ChangeLog	2019-09-26 02:01:53 UTC (rev 250375)
@@ -1,3 +1,128 @@
+2019-09-25  Jonathan Bedard  <jbed...@apple.com>
+
+        Python 3: Add support in webkitpy.common.system
+        https://bugs.webkit.org/show_bug.cgi?id=201826
+        <rdar://problem/55452671>
+
+        Reviewed by Stephanie Lewis.
+
+        Tested compatibility by running 'python3 -m unittest webkitpy.common.system.<_unittest>' on
+        each of the effected files.
+
+        * Scripts/webkitpy/common/checkout/changelog.py: Import StringIO from io module.
+        (set_reviewer):
+        (set_short_description_and_bug_url):
+        * Scripts/webkitpy/common/checkout/checkout.py:  Import StringIO from io module.
+        (Checkout._latest_entry_for_changelog_at_revision):
+        * Scripts/webkitpy/common/config/committers.py:
+        (CommitterList.load_json): iteritems -> items.
+        * Scripts/webkitpy/common/net/networktransaction.py:
+        (NetworkTransaction.run): urllib2 is urllib in Python3. 
+        * Scripts/webkitpy/common/system/abstractexecutive.py:
+        (AbstractExecutive._stringify_args):
+        (AbstractExecutive.command_for_printing): The str type is unicode in Python3.
+        * Scripts/webkitpy/common/system/crashlogs_unittest.py: Explicitly encode and decode binary crashlogs.
+        * Scripts/webkitpy/common/system/environment_unittest.py: Use absolute imports.
+        * Scripts/webkitpy/common/system/executive.py:
+        (ScriptError.message_with_output): The str type is unicode in Python3.
+        (Executive.WrappedPopen): Python3's Popen object is a context manager. To allow us to use it as one,
+        our Python2 Popen needs to be one as well.
+        (Executive.WrappedPopen.__init__):
+        (Executive.WrappedPopen.__enter__):
+        (Executive.WrappedPopen.__exit__):
+        (Executive._run_command_with_teed_output): Simplify loop, decode unicode strings.
+        (Executive.run_and_throw_if_fail): The child output file should not be unicode strings.
+        (Executive.running_pids): Use the Popen context manager to guarantee clean-up.
+        (Executive._compute_stdin):
+        (Executive.run_command): Use the Popen context manager to guarantee clean-up.
+        (Executive._stringify_args): The str type is unicode in Python3.
+        (Executive.popen): Return a context manager if the Popen object is not one.
+        * Scripts/webkitpy/common/system/executive_mock.py:
+        (MockProcess.__init__): StringIO -> BytesIO.
+        (MockProcess.__enter__):
+        (MockProcess):
+        (MockProcess.__exit__):
+        * Scripts/webkitpy/common/system/executive_unittest.py:
+        (ExecutiveTest.test_auto_stringify_args): Use the Popen context manager to guarantee clean-up.
+        (ExecutiveTest.test_popen_args): Ditto.
+        (ExecutiveTest.serial_test_kill_process): Ditto.
+        (ExecutiveTest.serial_test_kill_all): Ditto.
+        * Scripts/webkitpy/common/system/filesystem.py:
+        (FileSystem.read_binary_file): Use 'open' instead of 'file'.
+        (FileSystem.write_binary_file): Ditto.
+        (FileSystem.write_text_file): The str type is unicode in Python3. 
+        (FileSystem.relpath):
+        (FileSystem.remove): The WindowsError is just anther OSError in Python3.
+        (FileSystem._WindowsError): Deleted.
+        * Scripts/webkitpy/common/system/filesystem_mock.py:
+        (MockFileSystem.glob): filter returns a generator instead of a list.
+        (WritableBinaryFileObject.__init__): Binary files are comprised of bytes, not string in Python3.
+        (WritableBinaryFileObject.write): Ditto.
+        (ReadableTextFileObject.__init__): Ditto.
+        * Scripts/webkitpy/common/system/filesystem_mock_unittest.py:
+        (MockFileSystemTest.test_normpath):
+        (MockFileSystemTest.test_dirs_under): assertEquals -> assertEqual.
+        * Scripts/webkitpy/common/system/filesystem_unittest.py:
+        (RealFileSystemTest.test_read_and_write_file): Explicitly define byte arrays instead of strings.
+        (RealFileSystemTest.test_remove_file_with_retry.remove_with_exception): The WindowsError is just
+        anther OSError in Python3.
+        * Scripts/webkitpy/common/system/outputcapture.py:
+        * Scripts/webkitpy/common/system/outputtee_unittest.py:
+        (SimpleTeeTest.test_simple_tee):
+        * Scripts/webkitpy/common/system/path.py:
+        (_escape): urllib library has been broken into parts.
+        * Scripts/webkitpy/common/system/pemfile.py:
+        (_parse_pem_format.find_end): Python3 does not define a maxint.
+        * Scripts/webkitpy/common/system/pemfile_unittest.py:
+        * Scripts/webkitpy/common/system/platforminfo.py:
+        (PlatformInfo.total_bytes_memory): Not 'long' type in Python3.
+        * Scripts/webkitpy/common/system/platforminfo_unittest.py:
+        (TestPlatformInfo.test_real_code): assertNotEquals -> assertNotEqual.
+        (TestPlatformInfo.test_display_name): Ditto.
+        * Scripts/webkitpy/common/system/profiler.py:
+        (ProfilerFactory.create_profiler): Manually implement ifilter.
+        * Scripts/webkitpy/common/system/profiler_unittest.py: Use absolute imports.
+        * Scripts/webkitpy/common/system/stack_utils_unittest.py:
+        (current_thread_id): items() returns a generator in Python3.
+        * Scripts/webkitpy/common/system/systemhost.py: Use absolute imports.
+        * Scripts/webkitpy/common/system/urlfetcher.py: Removed.
+        * Scripts/webkitpy/common/system/urlfetcher_mock.py: Removed.
+        * Scripts/webkitpy/common/system/user.py:
+        (User.prompt): Use absolute imports, raw_input -> input.
+        (User.prompt_with_multiple_lists):
+        (User.prompt_with_list):
+        (User.confirm):
+        * Scripts/webkitpy/common/unicode.py: Tooling to manage compatibility between Python 2
+        and Python 3 unicode handling.
+        * Scripts/webkitpy/common/system/user_mock.py:
+        (MockUser.prompt): raw_input -> input.
+        (MockUser.prompt_with_list): Ditto.
+        * Scripts/webkitpy/common/version.py:
+        (Version.from_iterable): xrange -> range.
+        (Version.from_name): Use absolute import path.
+        (Version.__contains__): xrange -> range.
+        (Version.__str__): xrange -> range.
+        (Version.__cmp__): amp is no longer an operator in Python3, but versions are comprised
+        Of integers, so subtraction has the same effect.
+        (Version):
+        (Version.__eq__): __cmp__ operator is no longer respected, so we need to implement
+        each comparison.
+        (Version.__ne__): Ditto.
+        (Version.__lt__): Ditto.
+        (Version.__le__): Ditto.
+        (Version.__gt__): Ditto.
+        (Version.__ge__): Ditto.
+        * Scripts/webkitpy/common/version_name_map.py:
+        (VersionNameMap._automap_to_major_version):
+        (VersionNameMap.to_name): xrange -> range.
+        (VersionNameMap.from_name): iteritems -> items.
+        * Scripts/webkitpy/common/version_name_map_unittest.py: Use absolute imports.
+        * Scripts/webkitpy/common/version_unittest.py: Ditto.
+        * Scripts/webkitpy/common/wavediff.py:
+        (WaveDiff.__init__): StringIO -> BytesIO.
+        * Scripts/webkitpy/port/__init__.py:
+        (outside):
+
 2019-09-25  Aakash Jain  <aakash_j...@apple.com>
 
         [EWS] RunJavaScriptCoreTestsToT should use the same command as RunJavaScriptCoreTests

Modified: trunk/Tools/Scripts/webkitpy/common/checkout/changelog.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/checkout/changelog.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/changelog.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -30,11 +30,11 @@
 
 import logging
 import re
-from StringIO import StringIO
 import textwrap
 
 from webkitpy.common.config.committers import CommitterList
 from webkitpy.common.system.filesystem import FileSystem
+from webkitpy.common.unicode_compatibility import StringIO
 import webkitpy.common.config.urls as config_urls
 
 _log = logging.getLogger(__name__)

Modified: trunk/Tools/Scripts/webkitpy/common/checkout/checkout.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/checkout/checkout.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/checkout.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -26,8 +26,6 @@
 # (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 StringIO
-
 from webkitpy.common.config import urls
 from webkitpy.common.checkout.changelog import ChangeLog, parse_bug_id_from_changelog
 from webkitpy.common.checkout.commitinfo import CommitInfo
@@ -34,6 +32,7 @@
 from webkitpy.common.checkout.scm import CommitMessage
 from webkitpy.common.memoized import memoized
 from webkitpy.common.system.executive import ScriptError
+from webkitpy.common.unicode_compatibility import StringIO
 
 
 # This class represents the WebKit-specific parts of the checkout (like ChangeLogs).
@@ -61,7 +60,7 @@
         # that ChangeLog files are utf-8.  parse_latest_entry_from_file
         # expects a file-like object which vends unicode(), so we decode here.
         # Old revisions of Sources/WebKit/wx/ChangeLog have some invalid utf8 characters.
-        changelog_file = StringIO.StringIO(changelog_contents.decode("utf-8", "ignore"))
+        changelog_file = StringIO(changelog_contents.decode("utf-8", "ignore"))
         return ChangeLog.parse_latest_entry_from_file(changelog_file)
 
     def changelog_entries_for_revision(self, revision, changed_files=None):

Modified: trunk/Tools/Scripts/webkitpy/common/config/committers.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/config/committers.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/config/committers.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -201,7 +201,7 @@
         self._committers = []
         self._reviewers = []
 
-        for name, data in contributors.iteritems():
+        for name, data in contributors.items():
             contributor = None
             status = data.get('status')
             if status == "reviewer":

Modified: trunk/Tools/Scripts/webkitpy/common/net/networktransaction.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/net/networktransaction.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/net/networktransaction.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -27,9 +27,14 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import logging
+import sys
 import time
-import urllib2
 
+if sys.version_info > (3, 0):
+    from urllib.error import HTTPError, URLError
+else:
+    from urllib2 import HTTPError, URLError
+
 _log = logging.getLogger(__name__)
 
 
@@ -51,13 +56,13 @@
         while True:
             try:
                 return request()
-            except urllib2.HTTPError as e:
+            except HTTPError as e:
                 if self._convert_404_to_None and e.code == 404:
                     return None
                 self._check_for_timeout()
                 _log.warn("Received HTTP status %s loading \"%s\".  Retrying in %s seconds..." % (e.code, e.filename, self._backoff_seconds))
                 self._sleep()
-            except urllib2.URLError as e:
+            except URLError as e:
                 self._check_for_timeout()
                 _log.warn('Received URLError: "{}" while loading {}. Retrying in {} seconds...'.format(e.reason, url, self._backoff_seconds))
                 self._sleep()

Modified: trunk/Tools/Scripts/webkitpy/common/system/abstractexecutive.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/abstractexecutive.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/abstractexecutive.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -24,8 +24,8 @@
 import time
 
 from webkitpy.common.system.filesystem import FileSystem
+from webkitpy.common import unicode_compatibility
 
-
 class AbstractExecutive(object):
 
     def run_and_throw_if_fail(self, args, quiet=False, decode_output=True, **kwargs):
@@ -101,20 +101,13 @@
         pass
 
     def _stringify_args(self, args):
-        return map(unicode, args)
+        return map(unicode_compatibility.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)
+        return unicode_compatibility.decode_if_necessary(unicode_compatibility.encode_if_necessary(' '.join(args), 'unicode_escape'))
 
     def run_command(self, args, cwd=None, env=None, input=None, error_handler=None, ignore_errors=False,
         return_exit_code=False, return_stderr=True, decode_output=True):

Modified: trunk/Tools/Scripts/webkitpy/common/system/crashlogs.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/crashlogs.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/crashlogs.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -31,7 +31,9 @@
 import logging
 import re
 
+from webkitpy.common import unicode_compatibility
 
+
 _log = logging.getLogger(__name__)
 
 
@@ -109,7 +111,7 @@
         for path in reversed(sorted(logs)):
             try:
                 if not newer_than or self._host.filesystem.mtime(path) > newer_than:
-                    log_file = self._host.filesystem.read_binary_file(path).decode('ascii', 'ignore')
+                    log_file = unicode_compatibility.decode_if_necessary(self._host.filesystem.read_binary_file(path), 'ascii', 'ignore')
                     match = self.GLOBAL_PID_REGEX.search(log_file)
                     if match:
                         if int(match.group('pid')) == pid:

Modified: trunk/Tools/Scripts/webkitpy/common/system/crashlogs_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/crashlogs_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/crashlogs_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -27,7 +27,7 @@
 from webkitpy.common.system.filesystem_mock import MockFileSystem
 from webkitpy.common.system.systemhost import SystemHost
 from webkitpy.common.system.systemhost_mock import MockSystemHost
-from webkitpy.thirdparty.mock import Mock
+from webkitpy.common import unicode_compatibility
 
 # Needed to support Windows port tests
 from webkitpy.port.win import WinPort
@@ -298,6 +298,9 @@
         self.files['/Users/mock/Library/Logs/DiagnosticReports/DumpRenderTree_2011-06-13-150721_quadzen.crash'] = None
         self.files['/Users/mock/Library/Logs/DiagnosticReports/DumpRenderTree_2011-06-13-150722_quadzen.crash'] = self.other_process_mock_crash_report
         self.files['/Users/mock/Library/Logs/DiagnosticReports/DumpRenderTree_2011-06-13-150723_quadzen.crash'] = self.misformatted_mock_crash_report
+
+        self.files = {key: unicode_compatibility.encode_if_necessary(value) for key, value in self.files.items()}
+
         self.filesystem = MockFileSystem(self.files)
         crash_logs = CrashLogs(MockSystemHost(filesystem=self.filesystem), CrashLogsTest.DARWIN_MOCK_CRASH_DIRECTORY)
         logs = self.filesystem.files_under('/Users/mock/Library/Logs/DiagnosticReports/')
@@ -313,8 +316,8 @@
         all_logs = crash_logs.find_all_logs()
         self.assertEqual(len(all_logs), 8)
 
-        for test, crash_log in all_logs.iteritems():
-            self.assertTrue(crash_log in self.files.values())
+        for test, crash_log in all_logs.items():
+            self.assertTrue(crash_log in [unicode_compatibility.decode_if_necessary(value) for value in self.files.values()])
             if test.split('-')[0] != 'Sandbox':
                 self.assertTrue(test == "Unknown" or int(test.split("-")[1]) in range(28527, 28531))
 

Modified: trunk/Tools/Scripts/webkitpy/common/system/environment_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/environment_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/environment_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -28,7 +28,7 @@
 
 import unittest
 
-from .environment import Environment
+from webkitpy.common.system.environment import Environment
 
 
 class EnvironmentTest(unittest.TestCase):

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


--- trunk/Tools/Scripts/webkitpy/common/system/executive.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/executive.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -27,7 +27,6 @@
 # (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 StringIO
 import errno
 import logging
 import multiprocessing
@@ -39,6 +38,7 @@
 
 from webkitpy.common.system.abstractexecutive import AbstractExecutive
 from webkitpy.common.system.outputtee import Tee
+from webkitpy.common import unicode_compatibility
 
 
 _log = logging.getLogger(__name__)
@@ -71,7 +71,7 @@
                 return u"%s\n\nLast %s characters of output:\n%s" % \
                     (self, output_limit, self.output[-output_limit:])
             return u"%s\n\n%s" % (self, self.output)
-        return unicode(self)
+        return unicode_compatibility.unicode(self)
 
     def command_name(self):
         command_path = self.script_args
@@ -84,6 +84,19 @@
     PIPE = subprocess.PIPE
     STDOUT = subprocess.STDOUT
 
+    class WrappedPopen(object):
+        def __init__(self, popen):
+            for attribute in dir(popen):
+                if attribute.startswith('__'):
+                    continue
+                setattr(self, attribute, getattr(popen, attribute))
+
+        def __enter__(self):
+            return self
+
+        def __exit__(self, *args):
+            self.wait()
+
     def __init__(self):
         self.pid_to_system_pid = {}
         self._is_native_win = sys.platform.startswith('win')
@@ -108,18 +121,13 @@
                                    close_fds=self._should_close_fds(),
                                    **kwargs)
 
-        # Use our own custom wait loop because Popen ignores a tee'd
-        # stderr/stdout.
-        # FIXME: This could be improved not to flatten output to stdout.
-        while True:
-            output_line = child_process.stdout.readline()
-            if output_line == "" and child_process.poll() != None:
-                # poll() is not threadsafe and can throw OSError due to:
-                # http://bugs.python.org/issue1731717
-                return child_process.poll()
-            # We assume that the child process wrote to us in utf-8,
-            # so no re-encoding is necessary before writing here.
-            teed_output.write(output_line)
+        with child_process:
+            # Use our own custom wait loop because Popen ignores a tee'd
+            # stderr/stdout.
+            # FIXME: This could be improved not to flatten output to stdout.
+            while child_process.poll() is None:
+                output_line = child_process.stdout.readline()
+                teed_output.write(unicode_compatibility.decode_for(output_line, str))
 
     # FIXME: Remove this deprecated method and move callers to run_command.
     # FIXME: This method is a hack to allow running command which both
@@ -128,21 +136,25 @@
     # but still have the output to stuff into a log file.
     def run_and_throw_if_fail(self, args, quiet=False, decode_output=True, **kwargs):
         # Cache the child's output locally so it can be used for error reports.
-        child_out_file = StringIO.StringIO()
+        child_out_file = unicode_compatibility.StringIO()
         tee_stdout = sys.stdout
-        if quiet:
-            dev_null = open(os.devnull, "w")  # FIXME: Does this need an encoding?
-            tee_stdout = dev_null
-        child_stdout = Tee(child_out_file, tee_stdout)
-        exit_code = self._run_command_with_teed_output(args, child_stdout, **kwargs)
-        if quiet:
-            dev_null.close()
+        try:
+            if quiet:
+                dev_null = open(os.devnull, "w")  # FIXME: Does this need an encoding?
+                tee_stdout = dev_null
+            child_stdout = Tee(child_out_file, tee_stdout)
+            exit_code = self._run_command_with_teed_output(args, child_stdout, **kwargs)
+        finally:
+            if quiet:
+                dev_null.close()
 
         child_output = child_out_file.getvalue()
         child_out_file.close()
 
         if decode_output:
-            child_output = child_output.decode(self._child_process_encoding())
+            child_output = unicode_compatibility.decode_if_necessary(child_output, self._child_process_encoding())
+        else:
+            child_output = unicode_compatibility.encode_if_necessary(child_output, self._child_process_encoding())
 
         if exit_code:
             raise ScriptError(script_args=args,
@@ -286,17 +298,17 @@
                 except ValueError as e:
                     pass
         else:
-            ps_process = self.popen(['ps', '-eo', 'pid,comm'], stdout=self.PIPE, stderr=self.PIPE)
-            stdout, _ = ps_process.communicate()
-            for line in stdout.splitlines():
-                try:
-                    # In some cases the line can contain one or more
-                    # leading white-spaces, so strip it before split.
-                    pid, process_name = line.strip().split(' ', 1)
-                    if process_name_filter(process_name):
-                        running_pids.append(int(pid))
-                except ValueError as e:
-                    pass
+            with self.popen(['ps', '-eo', 'pid,comm'], stdout=self.PIPE, stderr=self.PIPE) as ps_process:
+                stdout, _ = ps_process.communicate()
+                for line in stdout.splitlines():
+                    try:
+                        # In some cases the line can contain one or more
+                        # leading white-spaces, so strip it before split.
+                        pid, process_name = line.strip().split(' ', 1)
+                        if process_name_filter(process_name):
+                            running_pids.append(int(pid))
+                    except ValueError as e:
+                        pass
 
         return sorted(running_pids)
 
@@ -355,8 +367,7 @@
         # See https://bugs.webkit.org/show_bug.cgi?id=37528
         # for an example of a regresion caused by passing a unicode string directly.
         # FIXME: We may need to encode differently on different platforms.
-        if isinstance(input, unicode):
-            input = input.encode(self._child_process_encoding())
+        input = unicode_compatibility.encode_if_necessary(input, self._child_process_encoding())
         return (self.PIPE, input)
 
     # FIXME: run_and_throw_if_fail should be merged into this method.
@@ -384,33 +395,37 @@
                              cwd=cwd,
                              env=env,
                              close_fds=self._should_close_fds())
-        output = process.communicate(string_to_communicate)[0]
+        with process:
+            if not string_to_communicate:
+                output = process.communicate()[0]
+            else:
+                output = process.communicate(unicode_compatibility.encode_if_necessary(string_to_communicate, 'utf-8'))[0]
 
-        # run_command automatically decodes to unicode() and converts CRLF to LF unless explicitly told not to.
-        if decode_output:
-            output = output.decode(self._child_process_encoding()).replace('\r\n', '\n')
+            # run_command automatically decodes to unicode() and converts CRLF to LF unless explicitly told not to.
+            if decode_output:
+                output = unicode_compatibility.decode_if_necessary(output, self._child_process_encoding()).replace('\r\n', '\n')
 
-        # wait() is not threadsafe and can throw OSError due to:
-        # http://bugs.python.org/issue1731717
-        exit_code = process.wait()
+            # wait() is not threadsafe and can throw OSError due to:
+            # http://bugs.python.org/issue1731717
+            exit_code = process.wait()
 
-        _log.debug('"%s" took %.2fs' % (self.command_for_printing(args), time.time() - start_time))
+            _log.debug('"%s" took %.2fs' % (self.command_for_printing(args), time.time() - start_time))
 
-        if return_exit_code:
-            return exit_code
+            if return_exit_code:
+                return exit_code
 
-        if exit_code:
-            script_error = ScriptError(script_args=args,
-                                       exit_code=exit_code,
-                                       output=output,
-                                       cwd=cwd)
+            if exit_code:
+                script_error = ScriptError(script_args=args,
+                                           exit_code=exit_code,
+                                           output=output,
+                                           cwd=cwd)
 
-            if ignore_errors:
-                assert error_handler is None, "don't specify error_handler if ignore_errors is True"
-                error_handler = Executive.ignore_error
+                if ignore_errors:
+                    assert error_handler is None, "don't specify error_handler if ignore_errors is True"
+                    error_handler = Executive.ignore_error
 
-            (error_handler or self.default_error_handler)(script_error)
-        return output
+                (error_handler or self.default_error_handler)(script_error)
+            return output
 
     def _child_process_encoding(self):
         # Win32 Python 2.x uses CreateProcessA rather than CreateProcessW
@@ -441,11 +456,11 @@
     def _encode_argument_if_needed(self, argument):
         if not self._should_encode_child_process_arguments():
             return argument
-        return argument.encode(self._child_process_encoding())
+        return unicode_compatibility.encode_if_necessary(argument, self._child_process_encoding())
 
     def _stringify_args(self, args):
         # Popen will throw an exception if args are non-strings (like int())
-        string_args = map(unicode, args)
+        string_args = map(unicode_compatibility.unicode, args)
         # The Windows implementation of Popen cannot handle unicode strings. :(
         return map(self._encode_argument_if_needed, string_args)
 
@@ -478,8 +493,13 @@
             string_args = args
         else:
             string_args = self._stringify_args(args)
-        return subprocess.Popen(string_args, **kwargs)
 
+        # Python 3 treats Popen as a context manager, we should allow this in Python 2
+        result = subprocess.Popen(string_args, **kwargs)
+        if not callable(getattr(result, "__enter__", None)) and not callable(getattr(result, "__exit__", None)):
+            return self.WrappedPopen(result)
+        return result
+
     def run_in_parallel(self, command_lines_and_cwds, processes=None):
         """Runs a list of (cmd_line list, cwd string) tuples in parallel and returns a list of (retcode, stdout, stderr) tuples."""
         assert len(command_lines_and_cwds)

Modified: trunk/Tools/Scripts/webkitpy/common/system/executive_mock.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/executive_mock.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/executive_mock.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -26,10 +26,10 @@
 # (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 StringIO
 import logging
 import os
 
+from webkitpy.common.unicode_compatibility import BytesIO, unicode
 from webkitpy.common.system.executive import ScriptError
 
 _log = logging.getLogger(__name__)
@@ -38,9 +38,9 @@
 class MockProcess(object):
     def __init__(self, stdout='MOCK STDOUT\n', stderr=''):
         self.pid = 42
-        self.stdout = StringIO.StringIO(stdout)
-        self.stderr = StringIO.StringIO(stderr)
-        self.stdin = StringIO.StringIO()
+        self.stdout = BytesIO(stdout)
+        self.stderr = BytesIO(stderr)
+        self.stdin = BytesIO()
         self.returncode = 0
         self._is_running = False
 
@@ -57,7 +57,13 @@
             return None
         return self.returncode
 
+    def __enter__(self):
+        return self
 
+    def __exit__(self, *args):
+        self.wait()
+
+
 # FIXME: This should be unified with MockExecutive2
 class MockExecutive(object):
     PIPE = "MOCK PIPE"

Modified: trunk/Tools/Scripts/webkitpy/common/system/executive_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/executive_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/executive_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -46,6 +46,7 @@
 
 from webkitpy.common.system.executive import Executive, ScriptError
 from webkitpy.common.system.filesystem_mock import MockFileSystem
+from webkitpy.common import unicode_compatibility
 
 
 class ScriptErrorTest(unittest.TestCase):
@@ -118,13 +119,15 @@
     def test_auto_stringify_args(self):
         executive = Executive()
         executive.run_command(command_line('echo', 1))
-        executive.popen(command_line('echo', 1), stdout=executive.PIPE).wait()
-        self.assertEqual('echo 1', executive.command_for_printing(['echo', 1]))
+        with executive.popen(command_line('echo', 1), stdout=executive.PIPE) as process:
+            process.wait()
+            self.assertEqual('echo 1', executive.command_for_printing(['echo', 1]))
 
     def test_popen_args(self):
         executive = Executive()
         # Explicitly naming the 'args' argument should not thow an exception.
-        executive.popen(args=command_line('echo', 1), stdout=executive.PIPE).wait()
+        with executive.popen(args=command_line('echo', 1), stdout=executive.PIPE) as process:
+            process.wait()
 
     def test_run_command_with_unicode(self):
         """Validate that it is safe to pass unicode() objects
@@ -135,11 +138,11 @@
             encoding = 'mbcs'
         else:
             encoding = 'utf-8'
-        encoded_tor = unicode_tor_input.encode(encoding)
+        encoded_tor = unicode_compatibility.encode_if_necessary(unicode_tor_input, encoding)
         # On Windows, we expect the unicode->mbcs->unicode roundtrip to be
         # lossy. On other platforms, we expect a lossless roundtrip.
         if sys.platform.startswith('win'):
-            unicode_tor_output = encoded_tor.decode(encoding)
+            unicode_tor_output = unicode_compatibility.decode_if_necessary(encoded_tor, encoding)
         else:
             unicode_tor_output = unicode_tor_input
 
@@ -167,44 +170,44 @@
 
     def serial_test_kill_process(self):
         executive = Executive()
-        process = subprocess.Popen(never_ending_command(), stdout=subprocess.PIPE)
-        self.assertEqual(process.poll(), None)  # Process is running
-        executive.kill_process(process.pid)
-        # Note: Can't use a ternary since signal.SIGKILL is undefined for sys.platform == "win32"
-        if sys.platform.startswith('win'):
-            # FIXME: https://bugs.webkit.org/show_bug.cgi?id=54790
-            # We seem to get either 0 or 1 here for some reason.
-            self.assertIn(process.wait(), (0, 1))
-        elif sys.platform == "cygwin":
-            # FIXME: https://bugs.webkit.org/show_bug.cgi?id=98196
-            # cygwin seems to give us either SIGABRT or SIGKILL
-            # Native Windows (via Cygwin) returns ENOTBLK (-15)
-            self.assertIn(process.wait(), (-signal.SIGABRT, -signal.SIGKILL, -15))
-        else:
-            expected_exit_code = -signal.SIGTERM
-            self.assertEqual(process.wait(), expected_exit_code)
+        with executive.popen(never_ending_command(), stdout=subprocess.PIPE) as process:
+            self.assertEqual(process.poll(), None)  # Process is running
+            executive.kill_process(process.pid)
+            # Note: Can't use a ternary since signal.SIGKILL is undefined for sys.platform == "win32"
+            if sys.platform.startswith('win'):
+                # FIXME: https://bugs.webkit.org/show_bug.cgi?id=54790
+                # We seem to get either 0 or 1 here for some reason.
+                self.assertIn(process.wait(), (0, 1))
+            elif sys.platform == "cygwin":
+                # FIXME: https://bugs.webkit.org/show_bug.cgi?id=98196
+                # cygwin seems to give us either SIGABRT or SIGKILL
+                # Native Windows (via Cygwin) returns ENOTBLK (-15)
+                self.assertIn(process.wait(), (-signal.SIGABRT, -signal.SIGKILL, -15))
+            else:
+                expected_exit_code = -signal.SIGTERM
+                self.assertEqual(process.wait(), expected_exit_code)
 
-        # Killing again should fail silently.
-        executive.kill_process(process.pid)
+            # Killing again should fail silently.
+            executive.kill_process(process.pid)
 
     def serial_test_kill_all(self):
         executive = Executive()
-        process = subprocess.Popen(never_ending_command(), stdout=subprocess.PIPE)
-        self.assertIsNone(process.poll())  # Process is running
-        executive.kill_all(never_ending_command()[0])
-        # Note: Can't use a ternary since signal.SIGTERM is undefined for sys.platform == "win32"
-        if sys.platform == "cygwin":
-            expected_exit_code = 0  # os.kill results in exit(0) for this process.
-            self.assertEqual(process.wait(), expected_exit_code)
-        elif sys.platform.startswith('win'):
-            # FIXME: https://bugs.webkit.org/show_bug.cgi?id=54790
-            # We seem to get either 0 or 1 here for some reason.
-            self.assertIn(process.wait(), (0, 1))
-        else:
-            expected_exit_code = -signal.SIGTERM
-            self.assertEqual(process.wait(), expected_exit_code)
-        # Killing again should fail silently.
-        executive.kill_all(never_ending_command()[0])
+        with executive.popen(never_ending_command(), stdout=subprocess.PIPE) as process:
+            self.assertIsNone(process.poll())  # Process is running
+            executive.kill_all(never_ending_command()[0])
+            # Note: Can't use a ternary since signal.SIGTERM is undefined for sys.platform == "win32"
+            if sys.platform == "cygwin":
+                expected_exit_code = 0  # os.kill results in exit(0) for this process.
+                self.assertEqual(process.wait(), expected_exit_code)
+            elif sys.platform.startswith('win'):
+                # FIXME: https://bugs.webkit.org/show_bug.cgi?id=54790
+                # We seem to get either 0 or 1 here for some reason.
+                self.assertIn(process.wait(), (0, 1))
+            else:
+                expected_exit_code = -signal.SIGTERM
+                self.assertEqual(process.wait(), expected_exit_code)
+            # Killing again should fail silently.
+            executive.kill_all(never_ending_command()[0])
 
     def _assert_windows_image_name(self, name, expected_windows_name):
         executive = Executive()

Modified: trunk/Tools/Scripts/webkitpy/common/system/filesystem.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/filesystem.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/filesystem.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -30,7 +30,6 @@
 
 import codecs
 import errno
-import exceptions
 import filecmp
 import glob
 import hashlib
@@ -40,7 +39,9 @@
 import tempfile
 import time
 
+from webkitpy.common.unicode_compatibility import decode_if_necessary
 
+
 class FileSystem(object):
     """FileSystem interface for webkitpy.
 
@@ -221,11 +222,11 @@
 
     def read_binary_file(self, path):
         """Return the contents of the file at the given path as a byte string."""
-        with file(path, 'rb') as f:
+        with open(path, 'rb') as f:
             return f.read()
 
     def write_binary_file(self, path, contents):
-        with file(path, 'wb') as f:
+        with open(path, 'wb') as f:
             f.write(contents)
 
     def open_text_file_for_reading(self, path, errors='strict'):
@@ -256,7 +257,7 @@
 
         The file is written encoded as UTF-8 with no BOM."""
         with codecs.open(path, 'w', 'utf-8', errors=errors) as f:
-            f.write(contents.decode('utf-8', errors=errors) if type(contents) == str else contents)
+            f.write(decode_if_necessary(contents, errors=errors))
 
     def sha1(self, path):
         contents = self.read_binary_file(path)
@@ -265,10 +266,6 @@
     def relpath(self, path, start='.'):
         return os.path.relpath(path, start)
 
-    class _WindowsError(exceptions.OSError):
-        """Fake exception for Linux and Mac."""
-        pass
-
     def remove(self, path, osremove=os.remove):
         """On Windows, if a process was recently killed and it held on to a
         file, the OS will hold on to the file for a short while.  This makes
@@ -275,9 +272,9 @@
         attempts to delete the file fail.  To work around that, this method
         will retry for a few seconds until Windows is done with the file."""
         try:
-            exceptions.WindowsError
-        except AttributeError:
-            exceptions.WindowsError = FileSystem._WindowsError
+            WinOSError = WindowsError
+        except NameError:
+            WinOSError = OSError
 
         retry_timeout_sec = 3.0
         sleep_interval = 0.1
@@ -285,7 +282,7 @@
             try:
                 osremove(path)
                 return True
-            except exceptions.WindowsError as e:
+            except WinOSError as e:
                 time.sleep(sleep_interval)
                 retry_timeout_sec -= sleep_interval
                 if retry_timeout_sec < 0:

Modified: trunk/Tools/Scripts/webkitpy/common/system/filesystem_mock.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/filesystem_mock.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/filesystem_mock.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -26,15 +26,15 @@
 # (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 StringIO
 import errno
 import hashlib
 import os
 import re
+import sys
 
+from webkitpy.common import unicode_compatibility
 from webkitpy.common.system import path
 
-
 class MockFileSystem(object):
     sep = '/'
     pardir = '..'
@@ -186,7 +186,7 @@
 
         # We could use fnmatch.fnmatch, but that might not do the right thing on windows.
         existing_files = [path for path, contents in self.files.items() if contents is not None]
-        return filter(path_filter, existing_files) + filter(path_filter, self.dirs)
+        return list(filter(path_filter, existing_files)) + list(filter(path_filter, self.dirs))
 
     def isabs(self, path):
         return path.startswith(self.sep)
@@ -344,7 +344,7 @@
         return self.read_binary_file(path).decode('utf-8', errors=errors)
 
     def write_text_file(self, path, contents, errors='strict'):
-        return self.write_binary_file(path, contents.encode('utf-8', errors=errors))
+        return self.write_binary_file(path, unicode_compatibility.encode_if_necessary(contents, 'utf-8', errors=errors))
 
     def sha1(self, path):
         contents = self.read_binary_file(path)
@@ -441,7 +441,7 @@
         self.fs = fs
         self.path = path
         self.closed = False
-        self.fs.files[path] = ""
+        self.fs.files[path] = b''
 
     def __enter__(self):
         return self
@@ -452,14 +452,14 @@
     def close(self):
         self.closed = True
 
-    def write(self, str):
-        self.fs.files[self.path] += str
+    def write(self, string):
+        self.fs.files[self.path] += unicode_compatibility.encode_if_necessary(string, 'utf-8')
         self.fs.written_files[self.path] = self.fs.files[self.path]
 
 
 class WritableTextFileObject(WritableBinaryFileObject):
     def write(self, str):
-        WritableBinaryFileObject.write(self, str.encode('utf-8'))
+        WritableBinaryFileObject.write(self, unicode_compatibility.encode_if_necessary(str, 'utf-8'))
 
 
 class ReadableBinaryFileObject(object):
@@ -489,7 +489,7 @@
 
 class ReadableTextFileObject(ReadableBinaryFileObject):
     def __init__(self, fs, path, data):
-        super(ReadableTextFileObject, self).__init__(fs, path, StringIO.StringIO(data.decode("utf-8")))
+        super(ReadableTextFileObject, self).__init__(fs, path, unicode_compatibility.UnicodeIO(unicode_compatibility.decode_for(data, unicode_compatibility.unicode)))
 
     def close(self):
         self.data.close()

Modified: trunk/Tools/Scripts/webkitpy/common/system/filesystem_mock_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/filesystem_mock_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/filesystem_mock_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -70,18 +70,18 @@
     def test_normpath(self):
         self.quick_check(self.fs.normpath,
                          self.fs._slow_but_correct_normpath,
-                         '',
-                         '/',
-                         '.',
-                         '/.',
-                         'foo',
-                         'foo/',
-                         'foo/.',
-                         'foo/bar',
-                         '/foo',
-                         'foo/../bar',
-                         'foo/../bar/baz',
-                         '../foo')
+                         ('',),
+                         ('/',),
+                         ('.',),
+                         ('/.',),
+                         ('foo',),
+                         ('foo/',),
+                         ('foo/.',),
+                         ('foo/bar',),
+                         ('/foo',),
+                         ('foo/../bar',),
+                         ('foo/../bar/baz',),
+                         ('../foo',))
 
     def test_dirs_under(self):
         FAKE_FILES = {
@@ -90,9 +90,9 @@
             '/tests/test2/test.txt': 'test'}
         fs = filesystem_mock.MockFileSystem(files=FAKE_FILES)
 
-        self.assertEquals(fs.dirs_under('/tests'), ['/tests', '/tests/test2', '/tests/test3', '/tests/test3/test2'])
+        self.assertEqual(fs.dirs_under('/tests'), ['/tests', '/tests/test2', '/tests/test3', '/tests/test3/test2'])
 
         def filter_dir(fs, dirpath):
             return fs.basename(dirpath) != 'test2'
 
-        self.assertEquals(fs.dirs_under('/tests', filter_dir), ['/tests', '/tests/test3'])
+        self.assertEqual(fs.dirs_under('/tests', filter_dir), ['/tests', '/tests/test3'])

Modified: trunk/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -37,7 +37,7 @@
 import tempfile
 import unittest
 
-from filesystem import FileSystem
+from webkitpy.common.system.filesystem import FileSystem
 
 
 class GenericFileSystemTests(object):
@@ -267,9 +267,9 @@
         binary_path = None
 
         unicode_text_string = u'\u016An\u012Dc\u014Dde\u033D'
-        hex_equivalent = '\xC5\xAA\x6E\xC4\xAD\x63\xC5\x8D\x64\x65\xCC\xBD'
-        malformed_text_hex = '\x4D\x69\x63\x72\x6F\x73\x6F\x66\x74\xAE\x20\x56\x69\x73\x75\x61\x6C\x20\x53\x74\x75\x64\x69\x6F\xAE\x20\x32\x30\x31\x30\x0D\x0A'
-        malformed_ignored_text_hex = '\x4D\x69\x63\x72\x6F\x73\x6F\x66\x74\x20\x56\x69\x73\x75\x61\x6C\x20\x53\x74\x75\x64\x69\x6F\x20\x32\x30\x31\x30\x0D\x0A'
+        hex_equivalent = b'\xC5\xAA\x6E\xC4\xAD\x63\xC5\x8D\x64\x65\xCC\xBD'
+        malformed_text_hex = b'\x4D\x69\x63\x72\x6F\x73\x6F\x66\x74\xAE\x20\x56\x69\x73\x75\x61\x6C\x20\x53\x74\x75\x64\x69\x6F\xAE\x20\x32\x30\x31\x30\x0D\x0A'
+        malformed_ignored_text_hex = b'\x4D\x69\x63\x72\x6F\x73\x6F\x66\x74\x20\x56\x69\x73\x75\x61\x6C\x20\x53\x74\x75\x64\x69\x6F\x20\x32\x30\x31\x30\x0D\x0A'
         try:
             text_path = tempfile.mktemp(prefix='tree_unittest_')
             binary_path = tempfile.mktemp(prefix='tree_unittest_')
@@ -285,8 +285,9 @@
             fs.write_binary_file(binary_path, malformed_text_hex)
             self.assertRaises(ValueError, fs.read_text_file, binary_path)
             text_contents = fs.read_binary_file(binary_path).decode('utf8', 'ignore')
-            self.assertEquals(text_contents, malformed_ignored_text_hex)
-            fs.open_text_file_for_reading(binary_path, 'replace').readline()
+            self.assertEqual(text_contents, malformed_ignored_text_hex.decode('utf8', 'ignore'))
+            with fs.open_text_file_for_reading(binary_path, 'replace') as file:
+                file.readline()
 
         finally:
             if text_path and fs.isfile(text_path):
@@ -311,7 +312,7 @@
                 try:
                     raise WindowsError
                 except NameError:
-                    raise FileSystem._WindowsError
+                    raise OSError
 
         fs = FileSystem()
         self.assertTrue(fs.remove('filename', remove_with_exception))

Modified: trunk/Tools/Scripts/webkitpy/common/system/outputcapture.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/outputcapture.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/outputcapture.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -31,9 +31,10 @@
 import logging
 import sys
 import unittest
-from StringIO import StringIO
 
+from webkitpy.common.unicode_compatibility import StringIO
 
+
 class OutputCapture(object):
     # By default we capture the output to a stream. Other modules may override
     # this function in order to do things like pass through the output. See

Modified: trunk/Tools/Scripts/webkitpy/common/system/outputtee_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/outputtee_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/outputtee_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -26,15 +26,15 @@
 # (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 StringIO
 import unittest
 
 from webkitpy.common.system.outputtee import Tee, OutputTee
+from webkitpy.common.unicode_compatibility import StringIO
 
 
 class SimpleTeeTest(unittest.TestCase):
     def test_simple_tee(self):
-        file1, file2 = StringIO.StringIO(), StringIO.StringIO()
+        file1, file2 = StringIO(), StringIO()
         tee = Tee(file1, file2)
         tee.write("foo bar\n")
         tee.write("baz\n")

Modified: trunk/Tools/Scripts/webkitpy/common/system/path.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/path.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/path.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -35,8 +35,12 @@
 import sys
 import logging
 import threading
-import urllib
 
+if sys.version_info > (3, 0):
+    from urllib.parse import quote as urllib_quote
+else:
+    from urllib import quote as urllib_quote
+
 _log = logging.getLogger(__name__)
 
 
@@ -146,7 +150,7 @@
     # when converting filenames to files. Instead of using urllib's default
     # rules, we allow a small list of other characters through un-escaped.
     # It's unclear if this is the best possible solution.
-    return urllib.quote(path, safe='/+:')
+    return urllib_quote(path, safe='/+:')
 
 
 def _convert_path(platform, path):

Modified: trunk/Tools/Scripts/webkitpy/common/system/pemfile.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/pemfile.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/pemfile.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -122,7 +122,7 @@
 
         try:
             index = lines.index(end_marker)
-        except ValueError, e:
+        except ValueError:
             raise BadFormatError("Cannot find section end: {}".format(end_marker))
 
         return kind, "\n".join(lines[0:index + 1]) + "\n", lines[index + 1:]

Modified: trunk/Tools/Scripts/webkitpy/common/system/pemfile_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/pemfile_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/pemfile_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -23,9 +23,9 @@
 
 
 import unittest
-import sys
 
 from webkitpy.common.system.pemfile import Pem, BadFormatError
+from webkitpy.common.system.platforminfo import PlatformInfo
 
 
 class PemFileTest(unittest.TestCase):
@@ -157,7 +157,7 @@
     # and split into a list of lines:
     lines = docstring.expandtabs().splitlines()
     # Determine minimum indentation (first line doesn't count):
-    indent = sys.maxint
+    indent = PlatformInfo.MAX
     for line in lines[1:]:
         stripped = line.lstrip()
         if stripped:
@@ -164,7 +164,7 @@
             indent = min(indent, len(line) - len(stripped))
     # Remove indentation (first line is special):
     trimmed = [lines[0].strip()]
-    if indent < sys.maxint:
+    if indent < PlatformInfo.MAX:
         for line in lines[1:]:
             trimmed.append(line[indent:].rstrip())
     # Strip off trailing and leading blank lines:

Modified: trunk/Tools/Scripts/webkitpy/common/system/platforminfo.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/platforminfo.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/platforminfo.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -36,6 +36,8 @@
 
 
 class PlatformInfo(object):
+    MAX = 2147483647
+
     """This class provides a consistent (and mockable) interpretation of
     system-specific values (like sys.platform and platform.mac_ver())
     to be used by the rest of the webkitpy code base.
@@ -118,11 +120,11 @@
 
     def total_bytes_memory(self):
         if self.is_mac():
-            return long(self._executive.run_command(["sysctl", "-n", "hw.memsize"]))
+            return int(self._executive.run_command(["sysctl", "-n", "hw.memsize"]))
         return None
 
     def terminal_width(self):
-        """Returns sys.maxint if the width cannot be determined."""
+        """Returns MAX if the width cannot be determined."""
         try:
             if self.is_win():
                 # From http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/
@@ -135,7 +137,7 @@
                     # Note that we return 1 less than the width since writing into the rightmost column
                     # automatically performs a line feed.
                     return right - left
-                return sys.maxint
+                return self.MAX
             else:
                 import fcntl
                 import struct
@@ -144,7 +146,7 @@
                 _, columns, _, _ = struct.unpack('HHHH', packed)
                 return columns
         except:
-            return sys.maxint
+            return self.MAX
 
     def build_version(self):
         if self.is_mac():

Modified: trunk/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -76,10 +76,10 @@
     def test_real_code(self):
         # This test makes sure the real (unmocked) code actually works.
         info = PlatformInfo(sys, platform, Executive())
-        self.assertNotEquals(info.os_name, '')
+        self.assertNotEqual(info.os_name, '')
         if info.is_mac() or info.is_win():
             self.assertIsNotNone(info.os_version)
-        self.assertNotEquals(info.display_name(), '')
+        self.assertNotEqual(info.display_name(), '')
         self.assertTrue(info.is_mac() or info.is_win() or info.is_linux() or info.is_freebsd())
         self.assertIsNotNone(info.terminal_width())
 
@@ -135,16 +135,16 @@
 
     def test_display_name(self):
         info = self.make_info(fake_sys('darwin'))
-        self.assertNotEquals(info.display_name(), '')
+        self.assertNotEqual(info.display_name(), '')
 
         info = self.make_info(fake_sys('win32'), fake_platform(win_version_string='6.1.7600'))
-        self.assertNotEquals(info.display_name(), '')
+        self.assertNotEqual(info.display_name(), '')
 
         info = self.make_info(fake_sys('linux2'), fake_platform('', '10.4'))
-        self.assertNotEquals(info.display_name(), '')
+        self.assertNotEqual(info.display_name(), '')
 
         info = self.make_info(fake_sys('freebsd9'), fake_platform('', '9.0-RELEASE'))
-        self.assertNotEquals(info.display_name(), '')
+        self.assertNotEqual(info.display_name(), '')
 
     def test_total_bytes_memory(self):
         info = self.make_info(fake_sys('darwin'), fake_platform('10.6.3'), fake_executive('1234'))

Modified: trunk/Tools/Scripts/webkitpy/common/system/profiler.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/profiler.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/profiler.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -29,8 +29,11 @@
 from __future__ import print_function
 import logging
 import re
-import itertools
+import sys
 
+if sys.version_info < (3, 0):
+    from itertools import ifilter  as filter
+
 _log = logging.getLogger(__name__)
 
 
@@ -41,7 +44,7 @@
         if not profilers:
             return None
         profiler_name = profiler_name or cls.default_profiler_name(host.platform)
-        profiler_class = next(itertools.ifilter(lambda profiler: profiler.name == profiler_name, profilers), None)
+        profiler_class = next(filter(lambda profiler: profiler.name == profiler_name, profilers), None)
         if not profiler_class:
             return None
         return profilers[0](host, executable_path, output_dir, identifier)

Modified: trunk/Tools/Scripts/webkitpy/common/system/profiler_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/profiler_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/profiler_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -31,7 +31,7 @@
 from webkitpy.common.system.platforminfo_mock import MockPlatformInfo
 from webkitpy.common.system.systemhost_mock import MockSystemHost
 
-from .profiler import ProfilerFactory, GooglePProf
+from webkitpy.common.system.profiler import ProfilerFactory, GooglePProf
 
 
 class ProfilerFactoryTest(unittest.TestCase):

Modified: trunk/Tools/Scripts/webkitpy/common/system/stack_utils_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/stack_utils_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/stack_utils_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -34,8 +34,9 @@
 
 
 def current_thread_id():
-    thread_id, _ = sys._current_frames().items()[0]
-    return thread_id
+    for thread_id in sys._current_frames().keys():
+        return thread_id
+    return None
 
 
 class StackUtilsTest(unittest.TestCase):

Modified: trunk/Tools/Scripts/webkitpy/common/system/systemhost.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/systemhost.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/systemhost.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -31,7 +31,7 @@
 import platform
 import sys
 
-from . import environment, executive, file_lock, filesystem, platforminfo, user, workspace
+from webkitpy.common.system import environment, executive, file_lock, filesystem, platforminfo, user, workspace
 
 
 class SystemHost(object):

Deleted: trunk/Tools/Scripts/webkitpy/common/system/urlfetcher.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/urlfetcher.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/urlfetcher.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -1,55 +0,0 @@
-# Copyright (C) 2011 Google 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:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * 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.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
-# OWNER OR 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.
-
-"""Wrapper module for fetching URLs."""
-
-import urllib
-
-
-class UrlFetcher(object):
-    """Class with restricted interface to fetch URLs (makes testing easier)"""
-    def __init__(self, filesystem):
-        self._filesystem = filesystem
-
-    def fetch(self, url):
-        """Fetches the contents of the URL as a string."""
-        file_object = urllib.urlopen(url)
-        content = file_object.read()
-        file_object.close()
-        return content
-
-    def fetch_into_file(self, url):
-        """Fetches the contents of the URL into a temporary file and return the filename.
-
-        This is the equivalent of urllib.retrieve() except that we don't return any headers.
-        """
-        file_object, filename = self._filesystem.open_binary_tempfile('-fetched')
-        contents = self.fetch(url)
-        file_object.write(contents)
-        file_object.close()
-        return filename

Deleted: trunk/Tools/Scripts/webkitpy/common/system/urlfetcher_mock.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/urlfetcher_mock.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/urlfetcher_mock.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -1,46 +0,0 @@
-# Copyright (C) 2011 Google 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:
-#
-#    * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#    * 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.
-#    * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
-# OWNER OR 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.
-
-
-def make_fetcher_cls(urls):
-    """UrlFetcher factory routine that simulates network access
-    using a dict of URLs -> contents."""
-    class MockFetcher(object):
-        def __init__(self, filesystem):
-            self._filesystem = filesystem
-
-        def fetch(self, url):
-            return urls[url]
-
-        def fetch_into_file(self, url):
-            f, fn = self._filesystem.open_binary_tempfile('mockfetcher')
-            f.write(self.fetch(url))
-            f.close()
-            return fn
-
-    return MockFetcher

Modified: trunk/Tools/Scripts/webkitpy/common/system/user.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/user.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/user.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -36,8 +36,8 @@
 import subprocess
 import webbrowser
 
-from .executive import Executive
-from .platforminfo import PlatformInfo
+from webkitpy.common.system.executive import Executive
+from webkitpy.common.system.platforminfo import PlatformInfo
 
 
 _log = logging.getLogger(__name__)
@@ -50,7 +50,12 @@
         # There is no readline module for win32, not much to do except cry.
         _log.warn("Unable to import readline.")
 
+if sys.version_info > (3, 0):
+    input_func = input
+else:
+    input_func = raw_input
 
+
 class User(object):
     DEFAULT_NO = 'n'
     DEFAULT_YES = 'y'
@@ -62,7 +67,7 @@
 
     # FIXME: These are @classmethods because bugzilla.py doesn't have a Tool object (thus no User instance).
     @classmethod
-    def prompt(cls, message, repeat=1, raw_input=raw_input):
+    def prompt(cls, message, repeat=1, raw_input=input_func):
         response = None
         while (repeat and not response):
             repeat -= 1
@@ -74,7 +79,7 @@
         return cls.prompt(message, repeat=repeat, raw_input=getpass.getpass)
 
     @classmethod
-    def prompt_with_multiple_lists(cls, list_title, subtitles, lists, can_choose_multiple=False, raw_input=raw_input):
+    def prompt_with_multiple_lists(cls, list_title, subtitles, lists, can_choose_multiple=False, raw_input=input_func):
         item_index = 0
         cumulated_list = []
         print(list_title)
@@ -114,7 +119,7 @@
                 return list_items[result]
 
     @classmethod
-    def prompt_with_list(cls, list_title, list_items, can_choose_multiple=False, raw_input=raw_input):
+    def prompt_with_list(cls, list_title, list_items, can_choose_multiple=False, raw_input=input_func):
         print(list_title)
         i = 0
         for item in list_items:
@@ -156,7 +161,7 @@
         except IOError as e:
             pass
 
-    def confirm(self, message=None, default=DEFAULT_YES, raw_input=raw_input):
+    def confirm(self, message=None, default=DEFAULT_YES, raw_input=input_func):
         if not message:
             message = "Continue?"
         choice = {'y': 'Y/n', 'n': 'y/N'}[default]

Modified: trunk/Tools/Scripts/webkitpy/common/system/user_mock.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/system/user_mock.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/system/user_mock.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -27,18 +27,22 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import logging
+import sys
 
 _log = logging.getLogger(__name__)
 
+if sys.version_info < (3, 0):
+    input = raw_input
 
+
 class MockUser(object):
 
     @classmethod
-    def prompt(cls, message, repeat=1, raw_input=raw_input):
+    def prompt(cls, message, repeat=1, raw_input=input):
         return "Mock user response"
 
     @classmethod
-    def prompt_with_list(cls, list_title, list_items, can_choose_multiple=False, raw_input=raw_input):
+    def prompt_with_list(cls, list_title, list_items, can_choose_multiple=False, raw_input=input):
         pass
 
     def __init__(self):

Added: trunk/Tools/Scripts/webkitpy/common/unicode_compatibility.py (0 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/unicode_compatibility.py	                        (rev 0)
+++ trunk/Tools/Scripts/webkitpy/common/unicode_compatibility.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -0,0 +1,56 @@
+# Copyright (C) 2019 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 io
+import sys
+
+
+BytesIO = io.BytesIO
+if sys.version_info > (3, 0):
+    StringIO = io.StringIO
+else:
+    from StringIO import StringIO
+UnicodeIO = io.StringIO
+
+unicode = str if sys.version_info > (3, 0) else unicode
+
+
+def encode_if_necessary(value, encoding='utf-8', errors='strict'):
+    # In Python 3, string types must be encoded
+    if type(value) == unicode:
+        return value.encode(encoding, errors=errors)
+    return value
+
+
+def decode_if_necessary(value, encoding='utf-8', errors='strict'):
+    # In Python 2, string types might need to be decoded
+    if type(value) == bytes:
+        return value.decode(encoding, errors=errors)
+    return value
+
+
+def decode_for(value, target_type):
+    if type(value) == target_type:
+        return value
+    if target_type == unicode:
+        return decode_if_necessary(bytes(value))
+    return value

Modified: trunk/Tools/Scripts/webkitpy/common/version.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/version.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/version.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -33,13 +33,13 @@
     @staticmethod
     def from_iterable(val):
         result = Version()
-        for i in xrange(len(val)):
+        for i in range(len(val)):
             result[i] = int(val[i])
         return result
 
     @staticmethod
     def from_name(name):
-        from version_name_map import VersionNameMap
+        from webkitpy.common.version_name_map import VersionNameMap
         return VersionNameMap.map().from_name(name)[1]
 
     def __init__(self, major=0, minor=0, tiny=0, micro=0, nano=0):
@@ -99,7 +99,7 @@
     def __contains__(self, version):
         assert isinstance(version, Version)
         does_match = True
-        for i in xrange(len(version)):
+        for i in range(len(version)):
             if self[i] != version[i]:
                 does_match = False
             if not does_match and self[i] != 0:
@@ -108,11 +108,11 @@
 
     def __str__(self):
         len_to_print = 1
-        for i in xrange(len(self)):
+        for i in range(len(self)):
             if self[i]:
                 len_to_print = i + 1
         result = str(self.major)
-        for i in xrange(len_to_print - 1):
+        for i in range(len_to_print - 1):
             result += '.{}'.format(self[i + 1])
         return result
 
@@ -119,7 +119,26 @@
     def __cmp__(self, other):
         if other is None:
             return 1
-        for i in xrange(len(self)):
-            if cmp(self[i], other[i]):
-                return cmp(self[i], other[i])
+        for i in range(len(self)):
+            diff = self[i] - other[i]
+            if diff:
+                return diff
         return 0
+
+    def __eq__(self, other):
+        return self.__cmp__(other) == 0
+
+    def __ne__(self, other):
+        return self.__cmp__(other) != 0
+
+    def __lt__(self, other):
+        return self.__cmp__(other) < 0
+
+    def __le__(self, other):
+        return self.__cmp__(other) <= 0
+
+    def __gt__(self, other):
+        return self.__cmp__(other) > 0
+
+    def __ge__(self, other):
+        return self.__cmp__(other) >= 0

Modified: trunk/Tools/Scripts/webkitpy/common/version_name_map.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/version_name_map.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/version_name_map.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -90,13 +90,13 @@
     def _automap_to_major_version(cls, prefix, minimum=Version(1), maximum=Version(1)):
         result = {}
         assert minimum <= maximum
-        for i in xrange((maximum.major + 1) - minimum.major):
+        for i in range((maximum.major + 1) - minimum.major):
             result['{} {}'.format(prefix, str(Version(minimum.major + i)))] = Version(minimum.major + i)
         return result
 
     def to_name(self, version, platform=None, table=PUBLIC_TABLE):
         closest_match = (None, None)
-        for os_name, os_version in self.mapping_for_platform(platform, table).iteritems():
+        for os_name, os_version in self.mapping_for_platform(platform, table).items():
             if version == os_version:
                 return os_name
             elif version in os_version:
@@ -126,16 +126,16 @@
 
     def from_name(self, name):
         # Exact match
-        for _, map in self.mapping.iteritems():
-            for os_name, os_map in map.iteritems():
+        for _, map in self.mapping.items():
+            for os_name, os_map in map.items():
                 if name in os_map:
                     return (os_name, os_map[name])
 
         # It's not an exact match, let's try unifying formatting
         unformatted = self.strip_name_formatting(name)
-        for _, map in self.mapping.iteritems():
-            for os_name, os_map in map.iteritems():
-                for version_name, version in os_map.iteritems():
+        for _, map in self.mapping.items():
+            for os_name, os_map in map.items():
+                for version_name, version in os_map.items():
                     if self.strip_name_formatting(version_name) == unformatted:
                         return (os_name, version)
         return (None, None)

Modified: trunk/Tools/Scripts/webkitpy/common/version_name_map_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/version_name_map_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/version_name_map_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -24,7 +24,7 @@
 
 from webkitpy.common.system.systemhost import SystemHost
 from webkitpy.common.version import Version
-from version_name_map import VersionNameMap
+from webkitpy.common.version_name_map import VersionNameMap
 
 
 class VersionMapTestCase(unittest.TestCase):

Modified: trunk/Tools/Scripts/webkitpy/common/version_unittest.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/version_unittest.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/version_unittest.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -22,7 +22,7 @@
 
 import unittest
 
-from version import Version
+from webkitpy.common.version import Version
 
 
 class VersionTestCase(unittest.TestCase):

Modified: trunk/Tools/Scripts/webkitpy/common/wavediff.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/common/wavediff.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/common/wavediff.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -20,13 +20,14 @@
 # (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 StringIO
 import struct
 import sys
 import tempfile
 import wave
 
+from io import BytesIO
 
+
 class WaveDiff(object):
     _paramNames = ('Number of channels', 'Sample width', 'Sample rate', 'Number of frames', 'Compression type', 'Compression name')
 
@@ -37,11 +38,11 @@
         if isinstance(in1, file):
             waveFile1 = wave.open(in1, 'rb')
         else:
-            waveFile1 = wave.open(StringIO.StringIO(in1), 'rb')
+            waveFile1 = wave.open(BytesIO(in1), 'rb')
         if isinstance(in2, file):
             waveFile1 = wave.open(in2, 'rb')
         else:
-            waveFile2 = wave.open(StringIO.StringIO(in2), 'rb')
+            waveFile2 = wave.open(BytesIO(in2), 'rb')
 
         params1 = waveFile1.getparams()
         params2 = waveFile2.getparams()

Modified: trunk/Tools/Scripts/webkitpy/port/__init__.py (250374 => 250375)


--- trunk/Tools/Scripts/webkitpy/port/__init__.py	2019-09-26 01:43:47 UTC (rev 250374)
+++ trunk/Tools/Scripts/webkitpy/port/__init__.py	2019-09-26 02:01:53 UTC (rev 250375)
@@ -28,8 +28,8 @@
 
 """Port-specific entrypoints for the layout tests test infrastructure."""
 
-import builders  # Why is this in port?
+import webkitpy.port.builders  # Why is this in port?
 
-from base import Port  # It's possible we don't need to export this virtual baseclass outside the module.
-from driver import Driver, DriverInput, DriverOutput
-from factory import platform_options, configuration_options
+from webkitpy.port.base import Port  # It's possible we don't need to export this virtual baseclass outside the module.
+from webkitpy.port.driver import Driver, DriverInput, DriverOutput
+from webkitpy.port.factory import platform_options, configuration_options
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to