[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-10851-g50815da

eric at webkit.org eric at webkit.org
Wed Dec 22 18:21:44 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit f1eeac35f30cad732a4a5a0da713ce566da0c13b
Author: eric at webkit.org <eric at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Dec 10 06:45:42 2010 +0000

    2010-12-09  Eric Seidel  <eric at webkit.org>
    
            Reviewed by Adam Barth.
    
            Teach webkit-patch how to search bugzilla
            https://bugs.webkit.org/show_bug.cgi?id=50500
    
            This is a step towards teaching webkitpy how to file
            new bugs for flaky tests and update them when new flakes occur.
    
            * Scripts/webkitpy/common/net/bugzilla/bugzilla.py:
            * Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py:
            * Scripts/webkitpy/tool/commands/__init__.py:
            * Scripts/webkitpy/tool/commands/bugsearch.py: Added.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@73688 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index d56c62f..ba6df0f 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,18 @@
+2010-12-09  Eric Seidel  <eric at webkit.org>
+
+        Reviewed by Adam Barth.
+
+        Teach webkit-patch how to search bugzilla
+        https://bugs.webkit.org/show_bug.cgi?id=50500
+
+        This is a step towards teaching webkitpy how to file
+        new bugs for flaky tests and update them when new flakes occur.
+
+        * Scripts/webkitpy/common/net/bugzilla/bugzilla.py:
+        * Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py:
+        * Scripts/webkitpy/tool/commands/__init__.py:
+        * Scripts/webkitpy/tool/commands/bugsearch.py: Added.
+
 2010-12-09  Adam Barth  <abarth at webkit.org>
 
         Reviewed by Ojan Vafai.
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
index 9fa7fe5..a0609c5 100644
--- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
@@ -33,6 +33,7 @@
 import os.path
 import re
 import StringIO
+import urllib
 
 from datetime import datetime # used in timestamp()
 
@@ -72,15 +73,39 @@ class BugzillaQueries(object):
     def __init__(self, bugzilla):
         self._bugzilla = bugzilla
 
-    # Note: _load_query and _fetch_bug are the only two methods which access
-    # self._bugzilla.
+    def _is_xml_bugs_form(self, form):
+        # ClientForm.HTMLForm.find_control throws if the control is not found,
+        # so we do a manual search instead:
+        return "xml" in [control.id for control in form.controls]
+
+    # This is kinda a hack.  There is probably a better way to get this information from bugzilla.
+    def _parse_result_count(self, results_page):
+        result_count_text = BeautifulSoup(results_page).find(attrs={'class': 'bz_result_count'}).string
+        result_count_parts = result_count_text.split(" ")
+        if result_count_parts[0] == "Zarro":
+            return 0
+        return int(result_count_parts[0])
+
+    # Note: _load_query, _fetch_bug and _fetch_bugs_from_advanced_query
+    # are the only methods which access self._bugzilla.
 
     def _load_query(self, query):
         self._bugzilla.authenticate()
-
         full_url = "%s%s" % (self._bugzilla.bug_server_url, query)
         return self._bugzilla.browser.open(full_url)
 
+    def _fetch_bugs_from_advanced_query(self, query):
+        results_page = self._load_query(query)
+        if not self._parse_result_count(results_page):
+            return []
+        # Bugzilla results pages have an "XML" submit button at the bottom
+        # which can be used to get an XML page containing all of the <bug> elements.
+        # This is slighty lame that this assumes that _load_query used
+        # self._bugzilla.browser and that it's in an acceptable state.
+        self._bugzilla.browser.select_form(predicate=self._is_xml_bugs_form)
+        bugs_xml = self._bugzilla.browser.submit()
+        return self._bugzilla._parse_bugs_from_xml(bugs_xml)
+
     def _fetch_bug(self, bug_id):
         return self._bugzilla.fetch_bug(bug_id)
 
@@ -114,6 +139,13 @@ class BugzillaQueries(object):
         needs_commit_query_url = "buglist.cgi?query_format=advanced&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=flagtypes.name&type0-0-0=equals&value0-0-0=review%2B"
         return self._fetch_bug_ids_advanced_query(needs_commit_query_url)
 
+    def fetch_bugs_matching_quicksearch(self, search_string):
+        # We may want to use a more explicit query than "quicksearch".
+        # If quicksearch changes we should probably change to use
+        # a normal buglist.cgi?query_format=advanced query.
+        quicksearch_url = "buglist.cgi?quicksearch=%s" % urllib.quote(search_string)
+        return self._fetch_bugs_from_advanced_query(quicksearch_url)
+
     def fetch_patches_from_pending_commit_list(self):
         return sum([self._fetch_bug(bug_id).reviewed_patches()
             for bug_id in self.fetch_bug_ids_from_pending_commit_list()], [])
@@ -250,7 +282,13 @@ class Bugzilla(object):
                 element, 'commit-queue', attachment, 'committer_email')
         return attachment
 
-    def _parse_bug_page(self, page):
+    def _parse_bugs_from_xml(self, page):
+        soup = BeautifulSoup(page)
+        # Without the unicode() call, BeautifulSoup occasionally complains of being
+        # passed None for no apparent reason.
+        return [Bug(self._parse_bug_dictionary_from_xml(unicode(bug_xml)), self) for bug_xml in soup('bug')]
+
+    def _parse_bug_dictionary_from_xml(self, page):
         soup = BeautifulSoup(page)
         bug = {}
         bug["id"] = int(soup.find("bug_id").string)
@@ -273,12 +311,12 @@ class Bugzilla(object):
 
     def fetch_bug_dictionary(self, bug_id):
         try:
-            return self._parse_bug_page(self._fetch_bug_page(bug_id))
+            return self._parse_bug_dictionary_from_xml(self._fetch_bug_page(bug_id))
         except KeyboardInterrupt:
             raise
         except:
             self.authenticate()
-            return self._parse_bug_page(self._fetch_bug_page(bug_id))
+            return self._parse_bug_dictionary_from_xml(self._fetch_bug_page(bug_id))
 
     # FIXME: A BugzillaCache object should provide all these fetch_ methods.
 
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py
index c476c81..9c03596 100644
--- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py
@@ -99,14 +99,7 @@ class BugzillaTest(unittest.TestCase):
         self.assertEquals(None, parse_bug_id("http://www.webkit.org/b/12345"))
         self.assertEquals(None, parse_bug_id("http://bugs.webkit.org/show_bug.cgi?ctype=xml&id=12345"))
 
-    _example_bug = """
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/bugzilla.dtd">
-<bugzilla version="3.2.3"
-          urlbase="https://bugs.webkit.org/"
-          maintainer="admin at webkit.org"
-          exporter="eric at webkit.org"
->
+    _bug_xml = """
     <bug>
           <bug_id>32585</bug_id>
           <creation_ts>2009-12-15 15:17 PST</creation_ts>
@@ -149,13 +142,13 @@ Ignore this bug.  Just for testing failure modes of webkit-patch and the commit-
             <type>text/plain</type> 
             <size>10882</size> 
             <attacher>mjs at apple.com</attacher> 
-            
+
               <token>1261988248-dc51409e9c421a4358f365fa8bec8357</token> 
               <data encoding="base64">SW5kZXg6IFdlYktpdC9tYWMvQ2hhbmdlTG9nCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09
 removed-because-it-was-really-long
 ZEZpbmlzaExvYWRXaXRoUmVhc29uOnJlYXNvbl07Cit9CisKIEBlbmQKIAogI2VuZGlmCg==
 </data>        
- 
+
             <flag name="review"
                 id="27602"
                 status="?"
@@ -163,8 +156,20 @@ ZEZpbmlzaExvYWRXaXRoUmVhc29uOnJlYXNvbl07Cit9CisKIEBlbmQKIAogI2VuZGlmCg==
             />
         </attachment>
     </bug>
-</bugzilla>
 """
+
+    _single_bug_xml = """
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/bugzilla.dtd">
+<bugzilla version="3.2.3"
+          urlbase="https://bugs.webkit.org/"
+          maintainer="admin at webkit.org"
+          exporter="eric at webkit.org"
+>
+%s
+</bugzilla>
+""" % _bug_xml
+
     _expected_example_bug_parsing = {
         "id" : 32585,
         "title" : u"bug to test webkit-patch and commit-queue failures",
@@ -194,10 +199,25 @@ ZEZpbmlzaExvYWRXaXRoUmVhc29uOnJlYXNvbl07Cit9CisKIEBlbmQKIAogI2VuZGlmCg==
         for key, expected_value in expected.items():
             self.assertEquals(actual[key], expected_value, ("Failure for key: %s: Actual='%s' Expected='%s'" % (key, actual[key], expected_value)))
 
-    def test_bug_parsing(self):
-        bug = Bugzilla()._parse_bug_page(self._example_bug)
+    def test_parse_bug_dictionary_from_xml(self):
+        bug = Bugzilla()._parse_bug_dictionary_from_xml(self._single_bug_xml)
         self._assert_dictionaries_equal(bug, self._expected_example_bug_parsing)
 
+    _sample_multi_bug_xml = """
+<bugzilla version="3.2.3" urlbase="https://bugs.webkit.org/" maintainer="admin at webkit.org" exporter="eric at webkit.org">
+    %s
+    %s
+</bugzilla>
+""" % (_bug_xml, _bug_xml)
+
+    def test_parse_bugs_from_xml(self):
+        bugzilla = Bugzilla()
+        bugs = bugzilla._parse_bugs_from_xml(self._sample_multi_bug_xml)
+        self.assertEquals(len(bugs), 2)
+        self.assertEquals(bugs[0].id(), self._expected_example_bug_parsing['id'])
+        bugs = bugzilla._parse_bugs_from_xml("")
+        self.assertEquals(len(bugs), 0)
+
     # This could be combined into test_bug_parsing later if desired.
     def test_attachment_parsing(self):
         bugzilla = Bugzilla()
@@ -328,6 +348,16 @@ class BugzillaQueriesTest(unittest.TestCase):
 </html>
 """
 
+    def _assert_result_count(self, queries, html, count):
+        self.assertEquals(queries._parse_result_count(html), count)
+
+    def test_parse_result_count(self):
+        queries = BugzillaQueries(None)
+        # Pages with results, always list the count at least twice.
+        self._assert_result_count(queries, '<span class="bz_result_count">314 bugs found.</span><span class="bz_result_count">314 bugs found.</span>', 314)
+        self._assert_result_count(queries, '<span class="bz_result_count">Zarro Boogs found.</span>', 0)
+        self.assertRaises(Exception, queries._parse_result_count, ['Invalid'])
+
     def test_request_page_parsing(self):
         queries = BugzillaQueries(None)
         self.assertEquals([40511, 40722, 40723], queries._parse_attachment_ids_request_query(self._sample_request_page))
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/__init__.py b/WebKitTools/Scripts/webkitpy/tool/commands/__init__.py
index d2aa503..bae26bf 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/__init__.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/__init__.py
@@ -1,5 +1,6 @@
 # Required for Python to search this directory for module files
 
+from webkitpy.tool.commands.bugsearch import BugSearch
 from webkitpy.tool.commands.download import *
 from webkitpy.tool.commands.earlywarningsystem import *
 from webkitpy.tool.commands.openbugs import OpenBugs
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/bugsearch.py b/WebKitTools/Scripts/webkitpy/tool/commands/bugsearch.py
new file mode 100644
index 0000000..5cbc1a0
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/bugsearch.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2010 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.
+
+from webkitpy.tool.multicommandtool import AbstractDeclarativeCommand
+
+
+class BugSearch(AbstractDeclarativeCommand):
+    name = "bug-search"
+    help_text = "List bugs matching a query"
+
+    def execute(self, options, args, tool):
+        search_string = args[0]
+        bugs = tool.bugs.queries.fetch_bugs_matching_quicksearch(search_string)
+        for bug in bugs:
+            print "%5s %s" % (bug.id(), bug.title())
+        if not bugs:
+            print "No bugs found matching '%s'" % search_string

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list