Title: [100233] trunk/Tools
Revision
100233
Author
[email protected]
Date
2011-11-14 19:08:16 -0800 (Mon, 14 Nov 2011)

Log Message

Improve ChangeLogEntry's reviewer parsing algorithm part 2
https://bugs.webkit.org/show_bug.cgi?id=72340

Reviewed by Eric Seidel.

This patch improves the recognition of NOBODY, wrestler names, and parenthesized clauses,
and prepares ChangeLogEntry to support edit-distance-based reviewer-name recognition.

* Scripts/webkitpy/common/checkout/changelog.py:
* Scripts/webkitpy/common/checkout/changelog_unittest.py:

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (100232 => 100233)


--- trunk/Tools/ChangeLog	2011-11-15 02:46:35 UTC (rev 100232)
+++ trunk/Tools/ChangeLog	2011-11-15 03:08:16 UTC (rev 100233)
@@ -1,3 +1,16 @@
+2011-11-14  Ryosuke Niwa  <[email protected]>
+
+        Improve ChangeLogEntry's reviewer parsing algorithm part 2
+        https://bugs.webkit.org/show_bug.cgi?id=72340
+
+        Reviewed by Eric Seidel.
+
+        This patch improves the recognition of NOBODY, wrestler names, and parenthesized clauses,
+        and prepares ChangeLogEntry to support edit-distance-based reviewer-name recognition.
+
+        * Scripts/webkitpy/common/checkout/changelog.py:
+        * Scripts/webkitpy/common/checkout/changelog_unittest.py:
+
 2011-11-14  Eric Seidel  <[email protected]>
 
         check-webkit-style broken by r99773: "Could not determine the port"

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


--- trunk/Tools/Scripts/webkitpy/common/checkout/changelog.py	2011-11-15 02:46:35 UTC (rev 100232)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/changelog.py	2011-11-15 03:08:16 UTC (rev 100233)
@@ -83,13 +83,28 @@
 
     reviewed_byless_regexp = r'^\s*((Review|Rubber(\s*|-)stamp)(s|ed)?|RS)(\s+|\s*=\s*)(?P<reviewer>([A-Z]\w+\s*)+)[\.,]?\s*$'
 
-    contributor_name_noise_regexp = re.compile(r"""
-    (\s+(landed|committed|)\s+by.+) # landed by, commented by, etc...
-    |\..+ # text afetr the first period (inclusive)
+    reviewer_name_noise_regexp = re.compile(r"""
+    (\s+((tweaked\s+)?and\s+)?(landed|committed|okayed)\s+by.+) # "landed by", "commented by", etc...
+    |(^(Reviewed\s+)?by\s+) # extra "Reviewed by" or "by"
+    |\.(?:(\s.+|$)) # text after the first period followed by a space
     |([(<]\s*[\w_\-\.]+@[\w_\-\.]+[>)]) # email addresses
-    |((?<=and)\s+([a-z\-]+\s+)+by) # phrases like "given a glance-over by" and "looked over by" (no capital letters)
+    |([(<](https?://?bugs.)webkit.org[^>)]+[>)]) # bug url
+    |("[^"]+") # wresler names like 'Sean/Shawn/Shaun' in 'Geoffrey "Sean/Shawn/Shaun" Garen'
+    |('[^']+') # wresler names like "The Belly" in "Sam 'The Belly' Weinig"
+    |((Mr|Ms|Dr|Mrs|Prof)\.(\s+|$))
     """, re.IGNORECASE | re.VERBOSE)
 
+    reviewer_name_casesensitive_noise_regexp = re.compile(r"""
+    ((\s+|^)(and\s+)?([a-z-]+\s+){5,}by\s+) # e.g. "and given a good once-over by"
+    |(\(\s*(?!(and|[A-Z])).+\)) # any parenthesis that doesn't start with "and" or a capital letter
+    |(with(\s+[a-z-]+)+) # phrases with "with no hesitation" in "Sam Weinig with no hesitation"
+    """, re.VERBOSE)
+
+    nobody_regexp = re.compile(r"""(\s+|^)nobody(
+    ((,|\s+-)?\s+(\w+\s+)+fix.*) # e.g. nobody, build fix...
+    |(\s*\([^)]+\).*) # NOBODY (..)...
+    |$)""", re.IGNORECASE | re.VERBOSE)
+
     # e.g. == Rolled over to ChangeLog-2011-02-16 ==
     rolled_over_regexp = r'^== Rolled over to ChangeLog-\d{4}-\d{2}-\d{2} ==$'
 
@@ -113,19 +128,24 @@
 
         reviewer_text = match.group("reviewer")
 
-        reviewer_text = ChangeLogEntry.contributor_name_noise_regexp.sub('', reviewer_text)
+        reviewer_text = ChangeLogEntry.nobody_regexp.sub('', reviewer_text)
+        reviewer_text = ChangeLogEntry.reviewer_name_noise_regexp.sub('', reviewer_text)
+        reviewer_text = ChangeLogEntry.reviewer_name_casesensitive_noise_regexp.sub('', reviewer_text)
+        reviewer_text = reviewer_text.replace('(', '').replace(')', '')
         reviewer_text = re.sub(r'\s\s+|[,.]\s*$', ' ', reviewer_text).strip()
+        if not len(reviewer_text):
+            return None, None
 
         # FIXME: Canonicalize reviewer names; e.g. Andy "First Time Reviewer" Estes
         # FIXME: Ignore NOBODY (\w+) and "a spell checker"
-        reviewer_list = re.split(r'\s*(?:(?:,(?:\s+and\s+|&)?)|(?:and\s+|&))\s*', reviewer_text)
+        reviewer_list = re.split(r'\s*(?:(?:,(?:\s+and\s+|&)?)|(?:and\s+|&)|(?:[/+]))\s*', reviewer_text)
 
         # Get rid of "reviewers" like "even though this is just a..." in "Reviewed by Sam Weinig, even though this is just a..."
-        reviewer_list = [reviewer for reviewer in reviewer_list if len(reviewer.split()) <= 5]
+        # and "who wrote the original code" in "Noam Rosenthal, who wrote the original code"
+        reviewer_list = [reviewer for reviewer in reviewer_list if not re.match('^who\s|^([a-z]+(\s+|\.|$)){6,}$', reviewer)]
 
         return reviewer_text, reviewer_list
 
-
     def _parse_entry(self):
         match = re.match(self.date_line_regexp, self._contents, re.MULTILINE)
         if not match:

Modified: trunk/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py (100232 => 100233)


--- trunk/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py	2011-11-15 02:46:35 UTC (rev 100232)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py	2011-11-15 03:08:16 UTC (rev 100233)
@@ -313,7 +313,6 @@
         self.assertEquals(reviewer_list, ['Alexey Proskuryakov'])
 
         reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Sam Weinig, and given a good once-over by Jeff Miller.')
-        self.assertEquals(reviewer_text, 'Sam Weinig, and Jeff Miller')
         self.assertEquals(reviewer_list, ['Sam Weinig', 'Jeff Miller'])
 
         reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed and landed by Brady Eidson')
@@ -323,6 +322,117 @@
         reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text(' Reviewed by Sam Weinig, even though this is just a...')
         self.assertEquals(reviewer_list, ['Sam Weinig'])
 
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by [email protected].')
+        self.assertEquals(reviewer_text, '[email protected]')
+        self.assertEquals(reviewer_list, ['[email protected]'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Dirk Schulze / Darin Adler.')
+        self.assertEquals(reviewer_text, 'Dirk Schulze / Darin Adler')
+        self.assertEquals(reviewer_list, ['Dirk Schulze', 'Darin Adler'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Sam Weinig + Oliver Hunt.')
+        self.assertEquals(reviewer_text, 'Sam Weinig + Oliver Hunt')
+        self.assertEquals(reviewer_list, ['Sam Weinig', 'Oliver Hunt'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Sam Weinig + Oliver Hunt.')
+        self.assertEquals(reviewer_text, 'Sam Weinig + Oliver Hunt')
+        self.assertEquals(reviewer_list, ['Sam Weinig', 'Oliver Hunt'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Rubber stamped by by Gustavo Noronha Silva')
+        self.assertEquals(reviewer_text, 'Gustavo Noronha Silva')
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Rubberstamped by Noam Rosenthal, who wrote the original code.')
+        self.assertEquals(reviewer_list, ['Noam Rosenthal'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Dan Bernstein (relanding of r47157)')
+        self.assertEquals(reviewer_list, ['Dan Bernstein'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Geoffrey "Sean/Shawn/Shaun" Garen')
+        self.assertEquals(reviewer_list, ['Geoffrey Garen'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Dave "Messy" Hyatt.')
+        self.assertEquals(reviewer_list, ['Dave Hyatt'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Sam \'The Belly\' Weinig')
+        self.assertEquals(reviewer_list, ['Sam Weinig'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Rubber-stamped by David "I\'d prefer not" Hyatt.')
+        self.assertEquals(reviewer_list, ['David Hyatt'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Mr. Geoffrey Garen.')
+        self.assertEquals(reviewer_list, ['Geoffrey Garen'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Darin (ages ago)')
+        self.assertEquals(reviewer_list, ['Darin'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Sam Weinig (except for a few comment and header tweaks).')
+        self.assertEquals(reviewer_list, ['Sam Weinig'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Sam Weinig (all but the FormDataListItem rename)')
+        self.assertEquals(reviewer_list, ['Sam Weinig'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Darin Adler, tweaked and landed by Beth.')
+        self.assertEquals(reviewer_list, ['Darin Adler'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Sam Weinig with no hesitation')
+        self.assertEquals(reviewer_list, ['Sam Weinig'])
+
+        # For now, we let unofficial reviewers recognized as reviewers
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Sam Weinig, Anders Carlsson, and (unofficially) Adam Barth.')
+        self.assertEquals(reviewer_list, ['Sam Weinig', 'Anders Carlsson', 'Adam Barth'])
+
+        # It's okay to have 'build fix' and 'others', etc... as a reviewer in the following cases because fuzzy-match would reject it
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Dimitri Glazkov, build fix')
+        self.assertEquals(reviewer_list, ['Dimitri Glazkov', 'build fix'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by BUILD FIX')
+        self.assertEquals(reviewer_list, ['BUILD FIX'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Mac build fix')
+        self.assertEquals(reviewer_list, ['Mac build fix'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Darin Adler, Dan Bernstein, Adele Peterson, and others.')
+        self.assertEquals(reviewer_text, 'Darin Adler, Dan Bernstein, Adele Peterson, and others')
+        self.assertEquals(reviewer_list, ['Darin Adler', 'Dan Bernstein', 'Adele Peterson', 'others'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by George Staikos (and others)')
+        self.assertEquals(reviewer_list, ['George Staikos', 'others'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Oliver Hunt, okayed by Darin Adler.')
+        self.assertEquals(reviewer_list, ['Oliver Hunt'])
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Mark Rowe, but Dan Bernstein also reviewed and asked thoughtful questions.')
+        self.assertEquals(reviewer_list, ['Mark Rowe', 'but Dan Bernstein also reviewed', 'asked thoughtful questions'])
+
+        # It's okay to have " in" and "by ", etc... in the following cases because we're going to fuzzy-match them later
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Darin Adler in <https://bugs.webkit.org/show_bug.cgi?id=47736>.')
+        self.assertEquals(reviewer_text, 'Darin Adler in')
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Adam Barth.:w')
+        self.assertEquals(reviewer_text, 'Adam Barth.:w')
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by Darin Adler).')
+        self.assertEquals(reviewer_text, 'Darin Adler')
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by NOBODY.')
+        self.assertEquals(reviewer_text, None)
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by NOBODY - Build Fix.')
+        self.assertEquals(reviewer_text, None)
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by NOBODY, layout tests fix.')
+        self.assertEquals(reviewer_text, None)
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by NOBODY (Qt build fix pt 2).')
+        self.assertEquals(reviewer_text, None)
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by NOBODY(rollout)')
+        self.assertEquals(reviewer_text, None)
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by NOBODY (Build fix, forgot to svn add this file)')
+        self.assertEquals(reviewer_text, None)
+
+        reviewer_text, reviewer_list = ChangeLogEntry._parse_reviewer_text('Reviewed by nobody (trivial follow up fix), Joseph Pecoraro LGTM-ed.')
+        self.assertEquals(reviewer_text, None)
+
     def test_latest_entry_parse(self):
         changelog_contents = u"%s\n%s" % (self._example_entry, self._example_changelog)
         changelog_file = StringIO(changelog_contents)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to