Python 3: Add support in webkitpy.tool
authorjbedard@apple.com <jbedard@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Dec 2019 00:10:42 +0000 (00:10 +0000)
committerjbedard@apple.com <jbedard@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Dec 2019 00:10:42 +0000 (00:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=204838

Reviewed by Stephanie Lewis.

* Scripts/test-webkitpy-python3: Add webkitpy.tool.
* Scripts/webkit-patch: Remove version check.
* Scripts/webkitpy/common/net/bugzilla/bug.py:
(Bug.reviewed_patches): Convert filter to list.
(Bug.commit_queued_patches): Ditto.
* Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py:
(MockBugzillaQueries.fetch_bug_ids_from_commit_queue): Convert map to list.
(MockBugzillaQueries.fetch_attachment_ids_from_review_queue): Ditto.
(MockBugzillaQueries.fetch_bug_ids_from_pending_commit_list): Ditto.
(MockBugzilla.post_comment_to_bug): Sort cc list before printing.
* Scripts/webkitpy/common/net/statusserver.py:
(StatusServer.set_api_key): Convert filter to list.
* Scripts/webkitpy/common/net/web.py:
(Web.get_binary): Use Python 2/3 compatible urlopen.
(Web.request): Use Python 2/3 compatible Request.
* Scripts/webkitpy/common/prettypatch.py:
(PrettyPatch.pretty_diff_file): Encode diff before printing.
* Scripts/webkitpy/common/system/executive_mock.py:
(MockExecutive.run_and_throw_if_fail): Sort environment before printing.
(MockExecutive.run_command): Convert input to string before printing.
* Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py:
(FailingTestCommitQueue.test_results): Convert map to list.
(MockSimpleTestPlanCommitQueue.test_results): Ditto.
* Scripts/webkitpy/tool/bot/feeders.py:
(CommitQueueFeeder.feed): Use Python 2/3 compatible sort.
(CommitQueueFeeder._patch_cmp): Deleted.
* Scripts/webkitpy/tool/bot/flakytestreporter.py:
(FlakyTestReporter._lookup_bug_for_flaky_test): Convert filter to list.
* Scripts/webkitpy/tool/bot/irc_command.py:
(Whois.execute): Convert map to list.
* Scripts/webkitpy/tool/bot/retrylogic_unittest.py:
(JSCEarlyWarningSystemTest._create_task): Convert map to list.
* Scripts/webkitpy/tool/bot/sheriff.py:
* Scripts/webkitpy/tool/commands/applywatchlistlocal_unittest.py: Use sorted lists
Instead of sets.
* Scripts/webkitpy/tool/commands/download.py:
(AbstractPatchSequencingCommand.__init__): Use Python 2/3 compatible sort.
* Scripts/webkitpy/tool/commands/download_unittest.py: Sort environment.
* Scripts/webkitpy/tool/commands/earlywarningsystem.py:
(AbstractEarlyWarningSystem.load_ews_classes): str.translate differs between Python 2
and Python 3.
* Scripts/webkitpy/tool/commands/newcommitbot.py:
(NewCommitBot._summarize_commit_log): Convert filter to list.
* Scripts/webkitpy/tool/commands/queues.py:
(AbstractQueue.should_continue_work_queue): Handle case where iterations is a MagicMock.
(AbstractQueue._log_from_script_error_for_upload): Explicitly use BytesIO
* Scripts/webkitpy/tool/commands/queues_unittest.py: Use explicit import paths.
* Scripts/webkitpy/tool/commands/rebaseline_unittest.py: Sort lists before comparing them.
* Scripts/webkitpy/tool/commands/stepsequence.py:
(StepSequence.options): Use Python 2/3 compatible sort.
* Scripts/webkitpy/tool/commands/suggestnominations.py:
(AbstractCommitLogCommand.__init__): Use Python 2/3 compatible sort.
(SuggestNominations._print_nominations): Ditto.
(SuggestNominations._print_counts): Ditto.
(SuggestNominations._print_nominations.nomination_cmp): Deleted.
(SuggestNominations._print_counts.counter_cmp): Deleted.
* Scripts/webkitpy/tool/mocktool_unittest.py: Use explicit import paths.
* Scripts/webkitpy/tool/multicommandtool.py:
(HelpCommand._help_epilog): Convert filter to list, use Python 2/3 compatible sort.
(MultiCommandTool._find_all_commands): Use Python 2/3 compatible sort.
* Scripts/webkitpy/tool/servers/gardeningserver.py:
(GardeningHTTPServer): Use Python 2/3 compatible HTTPServers.
* Scripts/webkitpy/tool/servers/rebaselineserver.py:
(get_test_baselines.AllPlatformsPort.baseline_search_path): Use list instead of utterable keys.
(RebaselineHTTPServer): Use Python 2/3 compatible HTTPServers.
(RebaselineHTTPServer.__init__): Ditto.
* Scripts/webkitpy/tool/servers/rebaselineserver_unittest.py:
(GetActualResultFilesTest.test): Use assertEqual instead of assertItemsEqual.
* Scripts/webkitpy/tool/servers/reflectionhandler.py:
(ReflectionHandler): Use Python 2/3 compatible HTTPServers.
* Scripts/webkitpy/tool/steps/applywatchlist.py:
(ApplyWatchList.run): Sort cc_emails before printing.
* Scripts/webkitpy/tool/steps/applywatchlist_unittest.py: Print sorted list instead
of set.
* Scripts/webkitpy/tool/steps/confirmdiff.py:
(ConfirmDiff._show_pretty_diff): Use Python 2/3 compatible pathname2url.
* Scripts/webkitpy/tool/steps/haslanded.py:
(HasLanded.convert_to_svn): Use Python 2/3 compatible StringIO.
(HasLanded.strip_change_log): Ditto.
* Scripts/webkitpy/tool/steps/preparechangelog.py:
(PrepareChangeLog._resolve_existing_entry): Convert zip object to list.
* Scripts/webkitpy/tool/steps/promptforbugortitle.py: Use Python 2/3 compatible urlparse.
* Scripts/webkitpy/tool/steps/steps_unittest.py: Sort environment.
* Scripts/webkitpy/w3c/test_exporter.py: Use Python 2/3 compatible HTTPError.
* Scripts/webkitpy/w3c/wpt_github.py:
(WPTGitHub.remove_label): Use Python 2/3 compatible urllib.quote.
(WPTGitHub.is_pr_merged): Use Python 2/3 compatible HTTPError.
(WPTGitHub.merge_pr): Ditto.
(JSONResponse.__init__):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@253128 268f45cc-cd09-0410-ab3c-d52691b4dbfc

40 files changed:
Tools/ChangeLog
Tools/Scripts/test-webkitpy-python3
Tools/Scripts/webkit-patch
Tools/Scripts/webkitpy/common/net/bugzilla/bug.py
Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py
Tools/Scripts/webkitpy/common/net/statusserver.py
Tools/Scripts/webkitpy/common/net/web.py
Tools/Scripts/webkitpy/common/prettypatch.py
Tools/Scripts/webkitpy/common/system/executive_mock.py
Tools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py
Tools/Scripts/webkitpy/tool/bot/feeders.py
Tools/Scripts/webkitpy/tool/bot/flakytestreporter.py
Tools/Scripts/webkitpy/tool/bot/irc_command.py
Tools/Scripts/webkitpy/tool/bot/retrylogic_unittest.py
Tools/Scripts/webkitpy/tool/bot/sheriff.py
Tools/Scripts/webkitpy/tool/commands/applywatchlistlocal_unittest.py
Tools/Scripts/webkitpy/tool/commands/download.py
Tools/Scripts/webkitpy/tool/commands/download_unittest.py
Tools/Scripts/webkitpy/tool/commands/earlywarningsystem.py
Tools/Scripts/webkitpy/tool/commands/newcommitbot.py
Tools/Scripts/webkitpy/tool/commands/queues.py
Tools/Scripts/webkitpy/tool/commands/queues_unittest.py
Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
Tools/Scripts/webkitpy/tool/commands/stepsequence.py
Tools/Scripts/webkitpy/tool/commands/suggestnominations.py
Tools/Scripts/webkitpy/tool/mocktool_unittest.py
Tools/Scripts/webkitpy/tool/multicommandtool.py
Tools/Scripts/webkitpy/tool/servers/gardeningserver.py
Tools/Scripts/webkitpy/tool/servers/rebaselineserver.py
Tools/Scripts/webkitpy/tool/servers/rebaselineserver_unittest.py
Tools/Scripts/webkitpy/tool/servers/reflectionhandler.py
Tools/Scripts/webkitpy/tool/steps/applywatchlist.py
Tools/Scripts/webkitpy/tool/steps/applywatchlist_unittest.py
Tools/Scripts/webkitpy/tool/steps/confirmdiff.py
Tools/Scripts/webkitpy/tool/steps/haslanded.py
Tools/Scripts/webkitpy/tool/steps/preparechangelog.py
Tools/Scripts/webkitpy/tool/steps/promptforbugortitle.py
Tools/Scripts/webkitpy/tool/steps/steps_unittest.py
Tools/Scripts/webkitpy/w3c/test_exporter.py
Tools/Scripts/webkitpy/w3c/wpt_github.py

index bd7d1d7..926b72d 100644 (file)
@@ -1,5 +1,102 @@
 2019-12-04  Jonathan Bedard  <jbedard@apple.com>
 
+        Python 3: Add support in webkitpy.tool
+        https://bugs.webkit.org/show_bug.cgi?id=204838
+
+        Reviewed by Stephanie Lewis.
+
+        * Scripts/test-webkitpy-python3: Add webkitpy.tool.
+        * Scripts/webkit-patch: Remove version check.
+        * Scripts/webkitpy/common/net/bugzilla/bug.py:
+        (Bug.reviewed_patches): Convert filter to list.
+        (Bug.commit_queued_patches): Ditto.
+        * Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py:
+        (MockBugzillaQueries.fetch_bug_ids_from_commit_queue): Convert map to list.
+        (MockBugzillaQueries.fetch_attachment_ids_from_review_queue): Ditto.
+        (MockBugzillaQueries.fetch_bug_ids_from_pending_commit_list): Ditto.
+        (MockBugzilla.post_comment_to_bug): Sort cc list before printing.
+        * Scripts/webkitpy/common/net/statusserver.py:
+        (StatusServer.set_api_key): Convert filter to list.
+        * Scripts/webkitpy/common/net/web.py:
+        (Web.get_binary): Use Python 2/3 compatible urlopen.
+        (Web.request): Use Python 2/3 compatible Request.
+        * Scripts/webkitpy/common/prettypatch.py:
+        (PrettyPatch.pretty_diff_file): Encode diff before printing.
+        * Scripts/webkitpy/common/system/executive_mock.py:
+        (MockExecutive.run_and_throw_if_fail): Sort environment before printing.
+        (MockExecutive.run_command): Convert input to string before printing.
+        * Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py:
+        (FailingTestCommitQueue.test_results): Convert map to list.
+        (MockSimpleTestPlanCommitQueue.test_results): Ditto.
+        * Scripts/webkitpy/tool/bot/feeders.py:
+        (CommitQueueFeeder.feed): Use Python 2/3 compatible sort.
+        (CommitQueueFeeder._patch_cmp): Deleted.
+        * Scripts/webkitpy/tool/bot/flakytestreporter.py:
+        (FlakyTestReporter._lookup_bug_for_flaky_test): Convert filter to list.
+        * Scripts/webkitpy/tool/bot/irc_command.py:
+        (Whois.execute): Convert map to list.
+        * Scripts/webkitpy/tool/bot/retrylogic_unittest.py:
+        (JSCEarlyWarningSystemTest._create_task): Convert map to list.
+        * Scripts/webkitpy/tool/bot/sheriff.py:
+        * Scripts/webkitpy/tool/commands/applywatchlistlocal_unittest.py: Use sorted lists
+        Instead of sets.
+        * Scripts/webkitpy/tool/commands/download.py:
+        (AbstractPatchSequencingCommand.__init__): Use Python 2/3 compatible sort.
+        * Scripts/webkitpy/tool/commands/download_unittest.py: Sort environment.
+        * Scripts/webkitpy/tool/commands/earlywarningsystem.py:
+        (AbstractEarlyWarningSystem.load_ews_classes): str.translate differs between Python 2
+        and Python 3.
+        * Scripts/webkitpy/tool/commands/newcommitbot.py:
+        (NewCommitBot._summarize_commit_log): Convert filter to list.
+        * Scripts/webkitpy/tool/commands/queues.py:
+        (AbstractQueue.should_continue_work_queue): Handle case where iterations is a MagicMock.
+        (AbstractQueue._log_from_script_error_for_upload): Explicitly use BytesIO
+        * Scripts/webkitpy/tool/commands/queues_unittest.py: Use explicit import paths.
+        * Scripts/webkitpy/tool/commands/rebaseline_unittest.py: Sort lists before comparing them.
+        * Scripts/webkitpy/tool/commands/stepsequence.py:
+        (StepSequence.options): Use Python 2/3 compatible sort.
+        * Scripts/webkitpy/tool/commands/suggestnominations.py:
+        (AbstractCommitLogCommand.__init__): Use Python 2/3 compatible sort.
+        (SuggestNominations._print_nominations): Ditto.
+        (SuggestNominations._print_counts): Ditto.
+        (SuggestNominations._print_nominations.nomination_cmp): Deleted.
+        (SuggestNominations._print_counts.counter_cmp): Deleted.
+        * Scripts/webkitpy/tool/mocktool_unittest.py: Use explicit import paths.
+        * Scripts/webkitpy/tool/multicommandtool.py:
+        (HelpCommand._help_epilog): Convert filter to list, use Python 2/3 compatible sort.
+        (MultiCommandTool._find_all_commands): Use Python 2/3 compatible sort.
+        * Scripts/webkitpy/tool/servers/gardeningserver.py:
+        (GardeningHTTPServer): Use Python 2/3 compatible HTTPServers.
+        * Scripts/webkitpy/tool/servers/rebaselineserver.py:
+        (get_test_baselines.AllPlatformsPort.baseline_search_path): Use list instead of utterable keys.
+        (RebaselineHTTPServer): Use Python 2/3 compatible HTTPServers.
+        (RebaselineHTTPServer.__init__): Ditto.
+        * Scripts/webkitpy/tool/servers/rebaselineserver_unittest.py:
+        (GetActualResultFilesTest.test): Use assertEqual instead of assertItemsEqual.
+        * Scripts/webkitpy/tool/servers/reflectionhandler.py:
+        (ReflectionHandler): Use Python 2/3 compatible HTTPServers.
+        * Scripts/webkitpy/tool/steps/applywatchlist.py:
+        (ApplyWatchList.run): Sort cc_emails before printing.
+        * Scripts/webkitpy/tool/steps/applywatchlist_unittest.py: Print sorted list instead
+        of set.
+        * Scripts/webkitpy/tool/steps/confirmdiff.py:
+        (ConfirmDiff._show_pretty_diff): Use Python 2/3 compatible pathname2url.
+        * Scripts/webkitpy/tool/steps/haslanded.py:
+        (HasLanded.convert_to_svn): Use Python 2/3 compatible StringIO.
+        (HasLanded.strip_change_log): Ditto.
+        * Scripts/webkitpy/tool/steps/preparechangelog.py:
+        (PrepareChangeLog._resolve_existing_entry): Convert zip object to list.
+        * Scripts/webkitpy/tool/steps/promptforbugortitle.py: Use Python 2/3 compatible urlparse.
+        * Scripts/webkitpy/tool/steps/steps_unittest.py: Sort environment.
+        * Scripts/webkitpy/w3c/test_exporter.py: Use Python 2/3 compatible HTTPError.
+        * Scripts/webkitpy/w3c/wpt_github.py:
+        (WPTGitHub.remove_label): Use Python 2/3 compatible urllib.quote.
+        (WPTGitHub.is_pr_merged): Use Python 2/3 compatible HTTPError.
+        (WPTGitHub.merge_pr): Ditto.
+        (JSONResponse.__init__):
+
+2019-12-04  Jonathan Bedard  <jbedard@apple.com>
+
         Unreviewed, rolling out r253069.
 
         requests not handling certificate chain correctly in Catalina
index 1273f1f..9b42a7c 100755 (executable)
@@ -41,6 +41,7 @@ PYTHON3_COMPATIBLE_DIRECTORIES = [
   'webkitpy.layout_tests.servers',
   'webkitpy.layout_tests.views',
   'webkitpy.port',
+  'webkitpy.tool',
   'webkitpy.results',
   'webkitpy.style',
   'webkitpy.xcode',
index 2ed9d8d..1635ca1 100755 (executable)
@@ -38,8 +38,6 @@ import signal
 import sys
 import codecs
 
-import webkitpy.common.version_check
-
 from webkitpy.common.system.logutils import configure_logging
 from webkitpy.tool.main import WebKitPatch
 
index d8e8cc1..bd8eac8 100644 (file)
@@ -110,7 +110,7 @@ class Bug(object):
             return patches
         # Checking reviewer() ensures that it was both reviewed and has a valid
         # reviewer.
-        return filter(lambda patch: patch.reviewer(), patches)
+        return list(filter(lambda patch: patch.reviewer(), patches))
 
     def commit_queued_patches(self, include_invalid=False):
         patches = [patch for patch in self.patches()
@@ -119,7 +119,7 @@ class Bug(object):
             return patches
         # Checking committer() ensures that it was both commit-queue+'d and has
         # a valid committer.
-        return filter(lambda patch: patch.committer(), patches)
+        return list(filter(lambda patch: patch.committer(), patches))
 
     def comments(self):
         return self.bug_dictionary["comments"]
index d67a86f..9e7c245 100644 (file)
@@ -323,7 +323,7 @@ class MockBugzillaQueries(object):
         bugs_with_commit_queued_patches = filter(
                 lambda bug: bug.commit_queued_patches(),
                 self._all_bugs())
-        return map(lambda bug: bug.id(), bugs_with_commit_queued_patches)
+        return list(map(lambda bug: bug.id(), bugs_with_commit_queued_patches))
 
     def fetch_attachment_ids_from_review_queue(self, since=None, only_security_bugs=False):
         unreviewed_patches = sum([bug.unreviewed_patches()
@@ -333,7 +333,7 @@ class MockBugzillaQueries(object):
                                         if patch.attach_date() >= since]
         if only_security_bugs:
             unreviewed_patches = filter(lambda patch: patch.bug().is_security_sensitive(), unreviewed_patches)
-        return map(lambda patch: patch.id(), unreviewed_patches)
+        return list(map(lambda patch: patch.id(), unreviewed_patches))
 
     def fetch_patches_from_commit_queue(self):
         return sum([bug.commit_queued_patches()
@@ -342,7 +342,7 @@ class MockBugzillaQueries(object):
     def fetch_bug_ids_from_pending_commit_list(self):
         bugs_with_reviewed_patches = filter(lambda bug: bug.reviewed_patches(),
                                             self._all_bugs())
-        bug_ids = map(lambda bug: bug.id(), bugs_with_reviewed_patches)
+        bug_ids = list(map(lambda bug: bug.id(), bugs_with_reviewed_patches))
         # NOTE: This manual hack here is to allow testing logging in
         # test_assign_to_committer the real pending-commit query on bugzilla
         # will return bugs with patches which have r+, but are also obsolete.
@@ -470,7 +470,7 @@ class MockBugzilla(object):
 
     def post_comment_to_bug(self, bug_id, comment_text, cc=None, see_also=None):
         _log.info("MOCK bug comment: bug_id=%s, cc=%s, see_also=%s\n--- Begin comment ---\n%s\n--- End comment ---\n" % (
-                  bug_id, cc, see_also, comment_text))
+                  bug_id, sorted(cc or []) or None, see_also, comment_text))
 
     def add_attachment_to_bug(self, bug_id, file_or_string, description, filename=None, comment_text=None, mimetype=None):
         _log.info("MOCK add_attachment_to_bug: bug_id=%s, description=%s filename=%s mimetype=%s" %
index 2c8aefe..25b6f17 100644 (file)
@@ -70,7 +70,7 @@ class StatusServer:
 
     def set_api_key(self, api_key):
         self._api_key = str(api_key)
-        new_headers = filter(lambda header: header[0] != self._AUTHORIZATION_HEADER_NAME, self._browser.addheaders)
+        new_headers = list(filter(lambda header: header[0] != self._AUTHORIZATION_HEADER_NAME, self._browser.addheaders))
         if api_key:
             new_headers.append(self._authorization_header_name_and_value_pair())
         self._browser.addheaders = new_headers
index 879aa07..536757c 100644 (file)
 # (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 urllib2
+import sys
 
 from webkitpy.common.net.networktransaction import NetworkTransaction
 
+if sys.version_info > (3, 0):
+    from urllib.request import build_opener, Request, urlopen, HTTPHandler
+else:
+    from urllib2 import urlopen, build_opener, Request, HTTPHandler
+
 
 class Web(object):
     def get_binary(self, url, convert_404_to_None=False):
-        return NetworkTransaction(convert_404_to_None=convert_404_to_None).run(lambda: urllib2.urlopen(url).read())
+        return NetworkTransaction(convert_404_to_None=convert_404_to_None).run(lambda: urlopen(url).read())
 
     def request(self, method, url, data, headers=None):
-        opener = urllib2.build_opener(urllib2.HTTPHandler)
-        request = urllib2.Request(url=url, data=data)
+        opener = build_opener(HTTPHandler)
+        request = Request(url=url, data=data)
         request.get_method = lambda: method
 
         if headers:
index 5768ceb..2eca002 100644 (file)
@@ -31,6 +31,7 @@ import logging
 import os
 import tempfile
 from webkitpy.common.system.executive import ScriptError
+from webkitpy.common.unicode_compatibility import encode_if_necessary
 
 _log = logging.getLogger(__name__)
 
@@ -49,8 +50,8 @@ class PrettyPatch(object):
     def pretty_diff_file(self, diff):
         # Diffs can contain multiple text files of different encodings
         # so we always deal with them as byte arrays, not unicode strings.
-        assert(isinstance(diff, str))
-        pretty_diff = self.pretty_diff(diff)
+        diff = encode_if_necessary(diff)
+        pretty_diff = encode_if_necessary(self.pretty_diff(diff))
         diff_file = tempfile.NamedTemporaryFile(suffix=".html")
         diff_file.write(pretty_diff)
         diff_file.flush()
index b89da30..3e6ba7b 100644 (file)
@@ -29,7 +29,7 @@
 import logging
 import os
 
-from webkitpy.common.unicode_compatibility import BytesIO, encode_if_necessary, unicode
+from webkitpy.common.unicode_compatibility import BytesIO, decode_for, encode_if_necessary, unicode
 from webkitpy.common.system.executive import ScriptError
 
 _log = logging.getLogger(__name__)
@@ -99,7 +99,11 @@ class MockExecutive(object):
         if self._should_log:
             env_string = ""
             if env:
-                env_string = ", env=%s" % env
+                for key in sorted(env.keys()):
+                    if len(env_string):
+                        env_string += ", "
+                    env_string += "'{}': '{}'".format(key, env[key])
+                env_string = ", env={" + env_string + "}"
             _log.info("MOCK run_and_throw_if_fail: %s, cwd=%s%s" % (args, cwd, env_string))
         if self._should_throw_when_run.intersection(args):
             raise ScriptError("Exception for %s" % args, output="MOCK command output")
@@ -126,10 +130,14 @@ class MockExecutive(object):
         if self._should_log:
             env_string = ""
             if env:
-                env_string = ", env=%s" % env
+                for key in sorted(env.keys()):
+                    if len(env_string):
+                        env_string += ", "
+                    env_string += "'{}': '{}'".format(key, env[key])
+                env_string = ", env={" + env_string + "}"
             input_string = ""
             if input:
-                input_string = ", input=%s" % input
+                input_string = ", input=%s" % decode_for(input, str)
             _log.info("MOCK run_command: %s, cwd=%s%s%s" % (args, cwd, env_string, input_string))
         output = "MOCK output of child process"
 
index 0d70dc8..bcf8863 100644 (file)
@@ -112,7 +112,7 @@ class FailingTestCommitQueue(MockCommitQueue):
         assert(self._test_run_counter >= 0)
         failures_for_run = self._test_failure_plan[self._test_run_counter]
         assert(isinstance(failures_for_run, list))
-        results = LayoutTestResults(test_results=map(self._mock_test_result, failures_for_run), did_exceed_test_failure_limit=(len(failures_for_run) >= 10))
+        results = LayoutTestResults(test_results=list(map(self._mock_test_result, failures_for_run)), did_exceed_test_failure_limit=(len(failures_for_run) >= 10))
         return results
 
 
@@ -147,7 +147,7 @@ class MockSimpleTestPlanCommitQueue(MockCommitQueue):
 
     def test_results(self):
         assert(isinstance(self._current_test_results, list))
-        return LayoutTestResults(test_results=map(self._mock_test_result, self._current_test_results), did_exceed_test_failure_limit=(len(self._current_test_results) >= 10))
+        return LayoutTestResults(test_results=list(map(self._mock_test_result, self._current_test_results)), did_exceed_test_failure_limit=(len(self._current_test_results) >= 10))
 
     def did_run_clean_tests(self):
         return self._did_run_clean_tests
@@ -159,7 +159,7 @@ class GoldenScriptError(ScriptError):
     pass
 
 
-_lots_of_failing_tests = map(lambda num: "test-%s.html" % num, range(0, 100))
+_lots_of_failing_tests = list(map(lambda num: "test-%s.html" % num, range(0, 100)))
 
 
 class CommitQueueTaskTest(unittest.TestCase):
index 275e4dc..b781b99 100644 (file)
@@ -54,7 +54,7 @@ class CommitQueueFeeder(AbstractFeeder):
     def feed(self):
         patches = self._validate_patches()
         patches = self._patches_with_acceptable_review_flag(patches)
-        patches = sorted(patches, self._patch_cmp)
+        patches = sorted(patches, key=lambda patch: patch.attach_date() or 0)
 
         high_priority_item_ids = [patch.id() for patch in patches if patch.is_rollout()]
         item_ids = [patch.id() for patch in patches if not patch.is_rollout()]
@@ -75,9 +75,6 @@ class CommitQueueFeeder(AbstractFeeder):
         all_patches = sum([self._patches_for_bug(bug_id) for bug_id in bug_ids], [])
         return self.committer_validator.patches_after_rejecting_invalid_commiters_and_reviewers(all_patches)
 
-    def _patch_cmp(self, a, b):
-        return cmp(a.attach_date(), b.attach_date())
-
 
 class EWSFeeder(AbstractFeeder):
     def __init__(self, tool):
index 929c899..25302b3 100644 (file)
@@ -73,7 +73,7 @@ class FlakyTestReporter(object):
             return None
         # Match any bugs which are from known bots or the email this bot is using.
         allowed_emails = self._bot_emails | set([self._bugzilla_email])
-        bugs = filter(lambda bug: bug.reporter_email() in allowed_emails, bugs)
+        bugs = list(filter(lambda bug: bug.reporter_email() in allowed_emails, bugs))
         if not bugs:
             return None
         if len(bugs) > 1:
index 67e07b0..483f71e 100644 (file)
@@ -35,6 +35,7 @@ from webkitpy.common.config import urls
 from webkitpy.common.config.committers import CommitterList
 from webkitpy.common.net.web import Web
 from webkitpy.common.system.executive import ScriptError
+from webkitpy.common.unicode_compatibility import unicode
 from webkitpy.tool.bot.queueengine import TerminateQueue
 from webkitpy.tool.grammar import join_with_separators
 from webkitpy.tool.grammar import pluralize
@@ -282,7 +283,7 @@ class Whois(IRCCommand):
             if not contributor.irc_nicknames:
                 return unicode("%s: %s hasn't told me their nick. Boo hoo :-(") % (nick, contributor)
             return unicode("%s: %s is %s. Why do you ask?") % (nick, search_string, self._full_record_and_nick(contributor))
-        contributor_nicks = map(self._full_record_and_nick, contributors)
+        contributor_nicks = list(map(self._full_record_and_nick, contributors))
         contributors_string = join_with_separators(contributor_nicks, only_two_separator=" or ", last_separator=', or ')
         return unicode("%s: I'm not sure who you mean?  %s could be '%s'.") % (nick, contributors_string, search_string)
 
index 9a72c7c..ac9896a 100644 (file)
@@ -85,7 +85,7 @@ class JSCEarlyWarningSystemTest(unittest.TestCase):
         queue = MockJSCEarlyWarningSystem(first_test_results, second_test_results, clean_test_results)
         tool = MockTool(log_executive=True)
         patch = tool.bugs.fetch_attachment(10000)
-        patches_passed_all_tests = map(self._results_indicate_all_passed, [second_test_results, first_test_results])
+        patches_passed_all_tests = list(map(self._results_indicate_all_passed, [second_test_results, first_test_results]))
         return MockPatchAnalysisTask(queue, patch, patches_passed_all_tests)
 
     def test_success_case(self):
index 9ef4875..fb87056 100644 (file)
@@ -30,6 +30,8 @@ from webkitpy.common.config import urls
 from webkitpy.common.system.executive import ScriptError
 from webkitpy.tool.grammar import join_with_separators
 
+from functools import reduce
+
 
 class Sheriff(object):
     def __init__(self, tool, sheriffbot):
index fdb5b22..8fe620a 100644 (file)
@@ -43,13 +43,13 @@ Message2."
 
     def test_args_parsing_with_bug(self):
         expected_logs = """MockWatchList: determine_cc_and_messages
-MOCK bug comment: bug_id=50002, cc=set(['eric@webkit.org', 'levin@chromium.org', 'abarth@webkit.org']), see_also=None
+MOCK bug comment: bug_id=50002, cc=['abarth@webkit.org', 'eric@webkit.org', 'levin@chromium.org'], see_also=None
 --- Begin comment ---
 Message1.
 
 Message2.
 --- End comment ---\n
-Result of watchlist: cc "eric@webkit.org, levin@chromium.org, abarth@webkit.org" messages "Message1.
+Result of watchlist: cc "abarth@webkit.org, eric@webkit.org, levin@chromium.org" messages "Message1.
 
 Message2."
 """
index 9d89771..8577025 100644 (file)
@@ -195,7 +195,7 @@ class AbstractPatchSequencingCommand(AbstractPatchProcessingCommand):
         options = []
         self._prepare_sequence = StepSequence(self.prepare_steps)
         self._main_sequence = StepSequence(self.main_steps)
-        options = sorted(set(self._prepare_sequence.options() + self._main_sequence.options()))
+        options = sorted(set(self._prepare_sequence.options() + self._main_sequence.options()), key=lambda option: option.dest)
         AbstractPatchProcessingCommand.__init__(self, options)
 
     def _prepare_to_process(self, options, args, tool):
index aa8cafc..aed6d11 100644 (file)
@@ -162,7 +162,7 @@ MOCK run_command: ['ruby', '-I', '/mock-checkout/Websites/bugs.webkit.org/Pretty
 MOCK: user.open_url: file://...
 Was that diff correct?
 Building WebKit
-MOCK run_and_throw_if_fail: ['mock-build-webkit', 'ARCHS=MOCK ARCH'], cwd=/mock-checkout, env={'TERM': 'dumb', 'MOCK_ENVIRON_COPY': '1'}
+MOCK run_and_throw_if_fail: ['mock-build-webkit', 'ARCHS=MOCK ARCH'], cwd=/mock-checkout, env={'MOCK_ENVIRON_COPY': '1', 'TERM': 'dumb'}
 Running Python unit tests
 MOCK run_and_throw_if_fail: ['mock-test-webkitpy'], cwd=/mock-checkout
 Running Perl unit tests
index 6bb6be2..9a556fd 100644 (file)
@@ -31,11 +31,13 @@ import json
 import logging
 import os
 from optparse import make_option
+import sys
 
 from webkitpy.common.config.committers import CommitterList
 from webkitpy.common.config.ports import DeprecatedPort
 from webkitpy.common.system.filesystem import FileSystem
 from webkitpy.common.system.executive import ScriptError
+from webkitpy.common.unicode_compatibility import encode_for
 from webkitpy.tool.bot.earlywarningsystemtask import EarlyWarningSystemTask, EarlyWarningSystemTaskDelegate
 from webkitpy.tool.bot.bindingstestresultsreader import BindingsTestResultsReader
 from webkitpy.tool.bot.layouttestresultsreader import LayoutTestResultsReader
@@ -174,8 +176,13 @@ class AbstractEarlyWarningSystem(AbstractReviewQueue, EarlyWarningSystemTaskDele
             return None
 
         classes = []
-        for name, config in ewses.iteritems():
-            classes.append(type(name.encode('utf-8').translate(None, ' -'), (cls,), {
+        for name, config in ewses.items():
+            if sys.version_info > (3, 0):
+                translated = encode_for(name, str).translate(' -')
+            else:
+                translated = encode_for(name, str).translate(None, ' -')
+
+            classes.append(type(translated, (cls,), {
                 'name': config.get('name', config['port'] + '-ews'),
                 'port_name': config['port'],
                 'architecture': config.get('architecture', None),
index abfdbe4..0de8b7f 100644 (file)
@@ -158,7 +158,7 @@ class NewCommitBot(AbstractQueue, StepSequenceErrorHandler):
                     linkified_revision, requested_by.group('reason'))
             lines[0] = '%s rolled out %s in %s' % (author, rollout.group('revisions'), linkified_revision)
 
-        return ' '.join(filter(lambda line: len(line), lines)[0:4])
+        return ' '.join(list(filter(lambda line: len(line), lines))[0:4])
 
     def handle_unexpected_error(self, failure_map, message):
         _log.error(message)
index 7fd2430..ff3eeef 100644 (file)
@@ -36,12 +36,12 @@ import time
 import traceback
 
 from optparse import make_option
-from StringIO import StringIO
 
 from webkitpy.common.config.committervalidator import CommitterValidator
 from webkitpy.common.config.ports import DeprecatedPort
 from webkitpy.common.net.bugzilla import Bugzilla, Attachment
 from webkitpy.common.system.executive import ScriptError
+from webkitpy.common.unicode_compatibility import BytesIO
 from webkitpy.tool.bot.botinfo import BotInfo
 from webkitpy.tool.bot.commitqueuetask import CommitQueueTask, CommitQueueTaskDelegate
 from webkitpy.tool.bot.feeders import CommitQueueFeeder, EWSFeeder
@@ -135,6 +135,8 @@ class AbstractQueue(Command, QueueEngineDelegate):
 
     def should_continue_work_queue(self):
         self._iteration_count += 1
+        if not isinstance(self._options.iterations, int):
+            return True
         return not self._options.iterations or self._iteration_count <= self._options.iterations
 
     def next_work_item(self):
@@ -163,7 +165,7 @@ class AbstractQueue(Command, QueueEngineDelegate):
         # We pre-encode the string to a byte array before passing it
         # to status_server, because ClientForm (part of mechanize)
         # wants a file-like object with pre-encoded data.
-        return StringIO(output.encode("utf-8"))
+        return BytesIO(output.encode("utf-8"))
 
     @classmethod
     def _update_status_for_script_error(cls, tool, state, script_error, is_error=False):
index 9ca66d4..ae8eafa 100644 (file)
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import os
-import StringIO
 
 from webkitpy.common.checkout.scm import CheckoutNeedsUpdate
 from webkitpy.common.checkout.scm.scm_mock import MockSCM
 from webkitpy.common.net.layouttestresults import LayoutTestResults
 from webkitpy.common.net.bugzilla import Attachment
 from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.unicode_compatibility import StringIO
 from webkitpy.layout_tests.models import test_results
 from webkitpy.layout_tests.models import test_failures
 from webkitpy.thirdparty.mock import Mock
index ab811d5..82cf5fa 100644 (file)
@@ -108,10 +108,12 @@ Bug(A) [ Debug ] : fast/css/large-list-of-rules-crash.html [ Failure ]
         self.options.suffixes = "png,wav,txt"
         self.command._rebaseline_test_and_update_expectations(self.options)
 
-        self.assertItemsEqual(self.tool.web.urls_fetched,
-            [self.WEB_PREFIX + '/userscripts/another-test-actual.png',
-             self.WEB_PREFIX + '/userscripts/another-test-actual.wav',
-             self.WEB_PREFIX + '/userscripts/another-test-actual.txt'])
+        self.assertEquals(
+            sorted(self.tool.web.urls_fetched), [
+                self.WEB_PREFIX + '/userscripts/another-test-actual.png',
+                self.WEB_PREFIX + '/userscripts/another-test-actual.txt',
+                self.WEB_PREFIX + '/userscripts/another-test-actual.wav',
+            ])
         new_expectations = self._read(self.lion_expectations_path)
         self.assertMultiLineEqual(new_expectations, """Bug(B) [ Mac Linux XP Debug ] fast/dom/Window/window-postmessage-clone-really-deep-array.html [ Pass ]
 Bug(A) [ Debug ] : fast/css/large-list-of-rules-crash.html [ Failure ]
@@ -124,10 +126,12 @@ Bug(A) [ Debug ] : fast/css/large-list-of-rules-crash.html [ Failure ]
         self.options.suffixes = 'png,wav,txt'
         self.command._rebaseline_test_and_update_expectations(self.options)
 
-        self.assertItemsEqual(self.tool.web.urls_fetched,
-            [self.WEB_PREFIX + '/userscripts/another-test-actual.png',
-             self.WEB_PREFIX + '/userscripts/another-test-actual.wav',
-             self.WEB_PREFIX + '/userscripts/another-test-actual.txt'])
+        self.assertEquals(
+            sorted(self.tool.web.urls_fetched), [
+                self.WEB_PREFIX + '/userscripts/another-test-actual.png',
+                self.WEB_PREFIX + '/userscripts/another-test-actual.txt',
+                self.WEB_PREFIX + '/userscripts/another-test-actual.wav',
+            ])
         new_expectations = self._read(self.lion_expectations_path)
         self.assertMultiLineEqual(new_expectations, "Bug(x) [ Mac ] userscripts/another-test.html [ ImageOnlyFailure ]\nbug(z) [ Linux ] userscripts/another-test.html [ ImageOnlyFailure ]\n")
 
@@ -138,23 +142,25 @@ Bug(A) [ Debug ] : fast/css/large-list-of-rules-crash.html [ Failure ]
         self.options.suffixes = 'png,wav,txt'
         self.command._rebaseline_test_and_update_expectations(self.options)
 
-        self.assertItemsEqual(self.tool.web.urls_fetched,
-            [self.WEB_PREFIX + '/userscripts/another-test-actual.png',
-             self.WEB_PREFIX + '/userscripts/another-test-actual.wav',
-             self.WEB_PREFIX + '/userscripts/another-test-actual.txt'])
+        self.assertEquals(
+            sorted(self.tool.web.urls_fetched), [
+                self.WEB_PREFIX + '/userscripts/another-test-actual.png',
+                self.WEB_PREFIX + '/userscripts/another-test-actual.txt',
+                self.WEB_PREFIX + '/userscripts/another-test-actual.wav',
+            ])
 
         new_expectations = self._read(self.lion_expectations_path)
         self.assertMultiLineEqual(new_expectations, "Bug(x) [ Mac ] userscripts/another-test.html [ ImageOnlyFailure ]\nBug(z) [ Linux ] userscripts/another-test.html [ ImageOnlyFailure ]\n")
 
     def test_rebaseline_test(self):
         self.command._rebaseline_test("Apple Lion Release WK1 (Tests)", "userscripts/another-test.html", None, "txt", self.WEB_PREFIX)
-        self.assertItemsEqual(self.tool.web.urls_fetched, [self.WEB_PREFIX + '/userscripts/another-test-actual.txt'])
+        self.assertEquals(self.tool.web.urls_fetched, [self.WEB_PREFIX + '/userscripts/another-test-actual.txt'])
 
     def test_rebaseline_test_with_results_directory(self):
         self._write(self.lion_expectations_path, "Bug(x) [ Mac ] userscripts/another-test.html [ ImageOnlyFailure ]\nbug(z) [ Linux ] userscripts/another-test.html [ ImageOnlyFailure ]\n")
         self.options.results_directory = '/tmp'
         self.command._rebaseline_test_and_update_expectations(self.options)
-        self.assertItemsEqual(self.tool.web.urls_fetched, ['file:///tmp/userscripts/another-test-actual.txt'])
+        self.assertEquals(self.tool.web.urls_fetched, ['file:///tmp/userscripts/another-test-actual.txt'])
 
     def test_rebaseline_test_and_print_scm_changes(self):
         self.command._print_scm_changes = True
@@ -184,7 +190,7 @@ Bug(A) [ Debug ] : fast/css/large-list-of-rules-crash.html [ Failure ]
 
         self.command._rebaseline_test("Apple Lion Release WK1 (Tests)", "userscripts/another-test.html", ["mac-lion-wk2"], "txt", self.WEB_PREFIX)
 
-        self.assertItemsEqual(self.tool.web.urls_fetched, [self.WEB_PREFIX + '/userscripts/another-test-actual.txt'])
+        self.assertEquals(self.tool.web.urls_fetched, [self.WEB_PREFIX + '/userscripts/another-test-actual.txt'])
         self.assertMultiLineEqual(self._read("platform/mac-lion-wk2/userscripts/another-test-expected.txt"), "original lion result")
         self.assertMultiLineEqual(self._read("platform/mac-lion-wk1/userscripts/another-test-expected.txt"), self.MOCK_WEB_RESULT)
 
@@ -295,7 +301,7 @@ class TestRebaseline(_BaseTestCase):
             oc.restore_output()
             builders._exact_matches = old_exact_matches
 
-        calls = filter(lambda x: x[0] not in ['perl', '/usr/bin/xcrun', '/usr/bin/ulimit'], self.tool.executive.calls)
+        calls = list(filter(lambda x: x[0] not in ['perl', '/usr/bin/xcrun', '/usr/bin/ulimit'], self.tool.executive.calls))
         self.assertEqual(calls,
             [[['echo', 'rebaseline-test-internal', '--suffixes', 'txt,png', '--builder', 'MOCK builder', '--test', 'mock/path/to/test.html', '--verbose']]])
 
@@ -317,7 +323,7 @@ class TestRebaselineExpectations(_BaseTestCase):
         self.command.execute(self.options, [], self.tool)
 
         # FIXME: change this to use the test- ports.
-        calls = filter(lambda x: x[0] not in ['perl', '/usr/bin/xcrun', '/usr/bin/ulimit'], self.tool.executive.calls)
+        calls = list(filter(lambda x: x[0] not in ['perl', '/usr/bin/xcrun', '/usr/bin/ulimit'], self.tool.executive.calls))
         self.assertEqual(len(calls), 1)
         self.assertEqual(len(calls[0]), 22)
 
index bb3c587..d39efc4 100644 (file)
@@ -59,7 +59,7 @@ class StepSequence(object):
         for step in self._steps:
             collected_options = collected_options + step.options()
         # Remove duplicates.
-        collected_options = sorted(set(collected_options))
+        collected_options = sorted(set(collected_options), key=lambda option: option.dest)
         return collected_options
 
     def _run(self, tool, options, state):
index e1e46f2..11a2401 100644 (file)
@@ -59,7 +59,7 @@ class AbstractCommitLogCommand(Command):
         options += [
             make_option("--max-commit-age", action="store", dest="max_commit_age", type="int", default=9, help="Specify maximum commit age to consider (in months)."),
         ]
-        options = sorted(options, cmp=lambda a, b: cmp(a._long_opts, b._long_opts))
+        options = sorted(options, key=lambda option: option.dest)
         super(AbstractCommitLogCommand, self).__init__(options=options)
         # FIXME: This should probably be on the tool somewhere.
         self._committer_list = CommitterList()
@@ -243,16 +243,11 @@ class SuggestNominations(AbstractCommitLogCommand):
         return nominations
 
     def _print_nominations(self, nominations, counters_by_email):
-        def nomination_cmp(a_nomination, b_nomination):
-            roles_result = cmp(a_nomination['roles'], b_nomination['roles'])
-            if roles_result:
-                return -roles_result
-            count_result = cmp(a_nomination['patch_count'], b_nomination['patch_count'])
-            if count_result:
-                return -count_result
-            return cmp(a_nomination['author_name'], b_nomination['author_name'])
-
-        for nomination in sorted(nominations, nomination_cmp):
+        nominations = sorted(nominations, key=lambda a: a['roles'])
+        nominations = sorted(nominations, key=lambda a: a['patch_count'])
+        nominations = sorted(nominations, key=lambda a: a['author_name'])
+
+        for nomination in nominations:
             # This is a little bit of a hack, but its convienent to just pass the nomination dictionary to the formating operator.
             nomination['roles_string'] = grammar.join_with_separators(nomination['roles']).upper()
             print("%(roles_string)s: %(author_name)s (%(author_email)s) has %(patch_count)s reviewed patches" % nomination)
@@ -262,18 +257,10 @@ class SuggestNominations(AbstractCommitLogCommand):
                 print(counter['commits'])
 
     def _print_counts(self, counters_by_email):
-        def counter_cmp(a_tuple, b_tuple):
-            # split the tuples
-            # the second element is the "counter" structure
-            _, a_counter = a_tuple
-            _, b_counter = b_tuple
-
-            count_result = cmp(a_counter['count'], b_counter['count'])
-            if count_result:
-                return -count_result
-            return cmp(a_counter['latest_name'].lower(), b_counter['latest_name'].lower())
-
-        for author_email, counter in sorted(counters_by_email.items(), counter_cmp):
+        counters = sorted(counters_by_email.items(), key=lambda counter: counter[1]['count'])
+        counters = sorted(counters, key=lambda counter: counter[1]['latest_name'])
+
+        for author_email, counter in counters:
             if author_email != counter['latest_email']:
                 continue
             contributor = self._committer_list.contributor_by_email(author_email)
index 5117909..027b95c 100644 (file)
@@ -28,7 +28,7 @@
 
 import unittest
 
-from mocktool import MockOptions
+from webkitpy.tool.mocktool import MockOptions
 
 
 class MockOptionsTest(unittest.TestCase):
index b65cee2..a795c92 100644 (file)
@@ -179,9 +179,9 @@ class HelpCommand(Command):
             relevant_commands = self._tool.commands[:]
         else:
             epilog = "Common %prog commands:\n"
-            relevant_commands = filter(self._tool.should_show_in_main_help, self._tool.commands)
+            relevant_commands = list(filter(self._tool.should_show_in_main_help, self._tool.commands))
         longest_name_length = max(map(lambda command: len(command.name), relevant_commands))
-        relevant_commands.sort(lambda a, b: cmp(a.name, b.name))
+        relevant_commands = sorted(relevant_commands, key=lambda command: command.name)
         command_help_texts = map(lambda command: "   %s   %s\n" % (command.name.ljust(longest_name_length), command.help_text), relevant_commands)
         epilog += "%s\n" % "".join(command_help_texts)
         epilog += "See '%prog help --all-commands' to list all commands.\n"
@@ -232,7 +232,7 @@ class MultiCommandTool(object):
     def _find_all_commands(cls):
         commands = set()
         cls._add_all_subclasses(Command, commands)
-        return sorted(commands)
+        return sorted(commands, key=lambda typ: typ.__name__)
 
     def name(self):
         return self._name
index ccd2957..68a7149 100644 (file)
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 from __future__ import print_function
-import BaseHTTPServer
-import SocketServer
+
 import logging
 import json
 import os
 import sys
 import urllib
 
+if sys.version_info > (3, 0):
+    from http.server import HTTPServer
+    from socketserver import ThreadingMixIn
+else:
+    from BaseHTTPServer import HTTPServer
+    from SocketServer import ThreadingMixIn
+
 from webkitpy.common.memoized import memoized
 from webkitpy.tool.servers.reflectionhandler import ReflectionHandler
 from webkitpy.port import builders
@@ -39,7 +45,7 @@ from webkitpy.port import builders
 _log = logging.getLogger(__name__)
 
 
-class GardeningHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
+class GardeningHTTPServer(ThreadingMixIn, HTTPServer):
     def __init__(self, httpd_port, config):
         server_name = ''
         self.tool = config['tool']
index ba9146c..2155e35 100644 (file)
 import fnmatch
 import os
 import os.path
-import BaseHTTPServer
+import sys
 
 from webkitpy.common.system.executive import ScriptError
 from webkitpy.port.base import Port
 from webkitpy.tool.servers.reflectionhandler import ReflectionHandler
 
+if sys.version_info > (3, 0):
+    from http.server import HTTPServer
+else:
+    from BaseHTTPServer import HTTPServer
+
 
 STATE_NEEDS_REBASELINE = 'needs_rebaseline'
 STATE_REBASELINE_FAILED = 'rebaseline_failed'
@@ -169,7 +174,7 @@ def get_test_baselines(test_file, test_config):
             self._platforms_by_directory = dict([(self._webkit_baseline_path(p), p) for p in test_config.platforms])
 
         def baseline_search_path(self, **kwargs):
-            return self._platforms_by_directory.keys()
+            return list(self._platforms_by_directory.keys())
 
         def platform_from_directory(self, directory):
             return self._platforms_by_directory[directory]
@@ -198,10 +203,10 @@ def get_test_baselines(test_file, test_config):
     return all_test_baselines
 
 
-class RebaselineHTTPServer(BaseHTTPServer.HTTPServer):
+class RebaselineHTTPServer(HTTPServer):
     def __init__(self, httpd_port, config):
         server_name = ""
-        BaseHTTPServer.HTTPServer.__init__(self, (server_name, httpd_port), RebaselineHTTPRequestHandler)
+        HTTPServer.__init__(self, (server_name, httpd_port), RebaselineHTTPRequestHandler)
         self.test_config = config['test_config']
         self.results_json = config['results_json']
         self.platforms_json = config['platforms_json']
index 25c82b9..dfca9e3 100644 (file)
@@ -234,7 +234,7 @@ class GetActualResultFilesTest(unittest.TestCase):
             'fast/text2-actual.txt',
             'fast/text-notactual.txt',
         ))
-        self.assertItemsEqual(
+        self.assertEqual(
             ('text-actual.txt',),
             rebaselineserver._get_actual_result_files(
                 'fast/text.html', test_config))
index 954fb56..db4b75d 100644 (file)
@@ -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 BaseHTTPServer
-
 import cgi
 import codecs
 import datetime
@@ -36,14 +34,19 @@ import json
 import mimetypes
 import os.path
 import shutil
+import sys
 import threading
 import time
-import urlparse
 import wsgiref.handlers
-import BaseHTTPServer
+
+if sys.version_info > (3, 0):
+    from http.server import BaseHTTPRequestHandler
+
+else:
+    from BaseHTTPServer import BaseHTTPRequestHandler
 
 
-class ReflectionHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+class ReflectionHandler(BaseHTTPRequestHandler):
     STATIC_FILE_EXTENSIONS = ['.js', '.css', '.html']
     # Subclasses should override.
     STATIC_FILE_DIRECTORY = None
index 2aa40d3..2132e25 100644 (file)
@@ -65,4 +65,4 @@ class ApplyWatchList(AbstractStep):
                 self._tool.bugs.post_comment_to_bug(bug_id, comment_text, cc_emails)
         else:
             _log.info('No bug was updated because no id was given.')
-        _log.info('Result of watchlist: cc "{}" messages "{}"'.format(', '.join(cc_emails), comment_text))
+        _log.info('Result of watchlist: cc "{}" messages "{}"'.format(', '.join(sorted(cc_emails)), comment_text))
index a5bdc0b..1a84d8c 100644 (file)
@@ -42,7 +42,7 @@ class ApplyWatchListTest(unittest.TestCase):
             'diff': 'The diff',
         }
         expected_logs = """MockWatchList: determine_cc_and_messages
-MOCK bug comment: bug_id=50001, cc=set(['levin@chromium.org']), see_also=None
+MOCK bug comment: bug_id=50001, cc=['levin@chromium.org'], see_also=None
 --- Begin comment ---
 Message2.
 --- End comment ---
index 4989312..5a20a7f 100644 (file)
@@ -26,7 +26,7 @@
 # (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 urllib
+import sys
 
 from webkitpy.tool.steps.abstractstep import AbstractStep
 from webkitpy.tool.steps.options import Options
@@ -34,6 +34,10 @@ from webkitpy.common.prettypatch import PrettyPatch
 from webkitpy.common.system import logutils
 from webkitpy.common.system.executive import ScriptError
 
+if sys.version_info > (3, 0):
+    from urllib.request import pathname2url
+else:
+    from urllib import pathname2url
 
 _log = logutils.get_logger(__file__)
 
@@ -53,7 +57,7 @@ class ConfirmDiff(AbstractStep):
             pretty_patch = PrettyPatch(self._tool.executive,
                                        self._tool.scm().checkout_root)
             pretty_diff_file = pretty_patch.pretty_diff_file(diff)
-            url = "file://%s" % urllib.pathname2url(pretty_diff_file.name)
+            url = "file://%s" % pathname2url(pretty_diff_file.name)
             self._tool.user.open_url(url)
             # We return the pretty_diff_file here because we need to keep the
             # file alive until the user has had a chance to confirm the diff.
index e86e4a4..fe3b782 100644 (file)
@@ -26,7 +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 cStringIO as StringIO
 import logging
 import sys
 import re
@@ -35,6 +34,7 @@ import tempfile
 from webkitpy.tool.steps.abstractstep import AbstractStep
 from webkitpy.common.system.executive import Executive, ScriptError
 from webkitpy.common.checkout import diff_parser
+from webkitpy.common.unicode_compatibility import StringIO
 
 from webkitpy.tool.steps import confirmdiff
 
@@ -45,7 +45,7 @@ class HasLanded(confirmdiff.ConfirmDiff):
 
     @classmethod
     def convert_to_svn(cls, diff):
-        lines = StringIO.StringIO(diff).readlines()
+        lines = StringIO(diff).readlines()
         convert = diff_parser.get_diff_converter(lines)
         return "".join(convert(x) for x in lines)
 
@@ -53,7 +53,7 @@ class HasLanded(confirmdiff.ConfirmDiff):
     def strip_change_log(cls, diff):
         output = []
         skipping = False
-        for line in StringIO.StringIO(diff).readlines():
+        for line in StringIO(diff).readlines():
             indexline = re.match("^Index: ([^\\n]*/)?([^/\\n]*)$", line)
             if skipping and indexline:
                 skipping = False
index 2812a15..46a33f6 100644 (file)
@@ -65,7 +65,7 @@ class PrepareChangeLog(AbstractStep):
         # by prepare-ChangeLog, as an clean updated version of the one below it.
         with self._tool.filesystem.open_text_file_for_reading(changelog_path) as changelog_file:
             entries_gen = ChangeLog.parse_entries_from_file(changelog_file)
-            entries = zip(entries_gen, range(2))
+            entries = list(zip(entries_gen, range(2)))
 
         if not len(entries):
             raise Exception("Expected to find at least two ChangeLog entries in %s but found none." % changelog_path)
index a323575..bd378d0 100644 (file)
 # (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 re
+import sys
+
 from webkitpy.tool.steps.abstractstep import AbstractStep
 from webkitpy.tool.steps.options import Options
-from urlparse import urlparse
-import re
+
+if sys.version_info > (3, 0):
+    from urllib.parse import urlparse
+else:
+    from urlparse import urlparse
+
 
 class PromptForBugOrTitle(AbstractStep):
     @classmethod
index 1d280a3..0a65c64 100644 (file)
@@ -188,7 +188,7 @@ MOCK run_and_throw_if_fail: ['Tools/Scripts/run-webkit-tests', '--debug', '--qui
         tool._deprecated_port = DeprecatedPort()
         step = steps.Build(tool, mock_options)
         expected_logs = """Building WebKit
-MOCK run_and_throw_if_fail: ['Tools/Scripts/build-jsc', '--debug', 'ARCHS=True'], cwd=/mock-checkout, env={'TERM': 'dumb', 'MOCK_ENVIRON_COPY': '1'}
+MOCK run_and_throw_if_fail: ['Tools/Scripts/build-jsc', '--debug', 'ARCHS=True'], cwd=/mock-checkout, env={'MOCK_ENVIRON_COPY': '1', 'TERM': 'dumb'}
 """
         OutputCapture().assert_outputs(self, step.run, [{}], expected_logs=expected_logs)
 
@@ -204,7 +204,7 @@ MOCK run_and_throw_if_fail: ['Tools/Scripts/build-jsc', '--debug', 'ARCHS=True']
         tool._deprecated_port = DeprecatedPort()
         step = steps.Build(tool, mock_options)
         expected_logs = """Building WebKit
-MOCK run_and_throw_if_fail: ['Tools/Scripts/build-jsc', '--release', 'ARCHS=True'], cwd=/mock-checkout, env={'TERM': 'dumb', 'MOCK_ENVIRON_COPY': '1'}
+MOCK run_and_throw_if_fail: ['Tools/Scripts/build-jsc', '--release', 'ARCHS=True'], cwd=/mock-checkout, env={'MOCK_ENVIRON_COPY': '1', 'TERM': 'dumb'}
 """
         OutputCapture().assert_outputs(self, step.run, [{}], expected_logs=expected_logs)
 
index d48db75..5f2a0e1 100644 (file)
@@ -29,7 +29,7 @@ import logging
 import os
 import time
 import json
-from urllib2 import HTTPError
+import sys
 
 from webkitpy.common.checkout.scm.git import Git
 from webkitpy.common.host import Host
@@ -40,6 +40,11 @@ from webkitpy.w3c.wpt_linter import WPTLinter
 from webkitpy.w3c.common import WPT_GH_ORG, WPT_GH_REPO_NAME, WPT_GH_URL, WPTPaths
 from webkitpy.common.memoized import memoized
 
+if sys.version_info > (3, 0):
+    from urllib.error import HTTPError
+else:
+    from urllib2 import HTTPError
+
 _log = logging.getLogger(__name__)
 
 WEBKIT_WPT_DIR = 'LayoutTests/imported/w3c/web-platform-tests'
index 8a62c49..7b5f1df 100644 (file)
@@ -30,12 +30,18 @@ import base64
 import json
 import logging
 import re
-import urllib2
+import sys
 from collections import namedtuple
 
 from webkitpy.common.memoized import memoized
 from webkitpy.w3c.common import WPT_GH_ORG, WPT_GH_REPO_NAME, EXPORT_PR_LABEL
 
+if sys.version_info > (3, 0):
+    from urllib.error import HTTPError
+    from urllib.parse import quote
+else:
+    from urllib2 import HTTPError, quote
+
 _log = logging.getLogger(__name__)
 API_BASE = 'https://api.github.com'
 MAX_PER_PAGE = 100
@@ -192,7 +198,7 @@ class WPTGitHub(object):
             WPT_GH_ORG,
             WPT_GH_REPO_NAME,
             number,
-            urllib2.quote(label),
+            quote(label),
         )
         response = self.request(path, method='DELETE')
 
@@ -285,7 +291,7 @@ class WPTGitHub(object):
                 return True
             else:
                 raise GitHubError(204, response.status_code, 'check if PR %d is merged' % pr_number)
-        except urllib2.HTTPError as e:
+        except HTTPError as e:
             if e.code == 404:
                 return False
             else:
@@ -310,7 +316,7 @@ class WPTGitHub(object):
 
         try:
             response = self.request(path, method='PUT', body=body)
-        except urllib2.HTTPError as e:
+        except HTTPError as e:
             if e.code == 405:
                 raise MergeError(pr_number)
             else:
@@ -385,7 +391,7 @@ class JSONResponse(object):
         """Initializes a JSONResponse instance.
 
         Args:
-            raw_response: a response object returned by open methods in urllib2.
+            raw_response: a response object returned by open methods in urllib2/urllib.
         """
         self._raw_response = raw_response
         self.status_code = raw_response.getcode()