1517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org#!/usr/bin/python2 2517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 3517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org# Copyright 2014 Google Inc. 4517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org# 5517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org# Use of this source code is governed by a BSD-style license that can be 6517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org# found in the LICENSE file. 7517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 8517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org"""Skia's Chromium Codereview Comparison Script. 9517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 10517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgThis script takes two Codereview URLs, looks at the trybot results for 11517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgthe two codereviews and compares the results. 12517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 13517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgUsage: 14517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org compare_codereview.py CONTROL_URL ROLL_URL 15517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org""" 16517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 17517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgimport collections 18517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgimport os 19517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgimport re 20517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgimport sys 21517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgimport urllib2 22517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgimport HTMLParser 23517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 24517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 25517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgclass CodeReviewHTMLParser(HTMLParser.HTMLParser): 262a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Parses CodeReview web page. 27517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 282a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org Use the CodeReviewHTMLParser.parse static function to make use of 292a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org this class. 30517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 312a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org This uses the HTMLParser class because it's the best thing in 322a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org Python's standard library. We need a little more power than a 332a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org regex. [Search for "You can't parse [X]HTML with regex." for more 342a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org information. 352a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """ 362a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # pylint: disable=I0011,R0904 372a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org @staticmethod 382a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org def parse(url): 392a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Parses a CodeReview web pages. 402a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 412a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org Args: 422a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org url (string), a codereview URL like this: 432a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 'https://codereview.chromium.org/?????????'. 442a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 452a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org Returns: 462a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org A dictionary; the keys are bot_name strings, the values 472a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org are CodeReviewHTMLParser.Status objects 482a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """ 492a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org parser = CodeReviewHTMLParser() 502a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org try: 512a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org parser.feed(urllib2.urlopen(url).read()) 522a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org except (urllib2.URLError,): 532a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org print >> sys.stderr, 'Error getting', url 542a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org return None 552a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org parser.close() 562a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org return parser.statuses 572a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 582a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # namedtuples are like lightweight structs in Python. The low 592a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # overhead of a tuple, but the ease of use of an object. 602a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org Status = collections.namedtuple('Status', ['status', 'url']) 612a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 622a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org def __init__(self): 632a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org HTMLParser.HTMLParser.__init__(self) 642a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._id = None 652a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._status = None 662a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._href = None 672a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._anchor_data = '' 682a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._currently_parsing_trybotdiv = False 692a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # statuses is a dictionary of CodeReviewHTMLParser.Status 702a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self.statuses = {} 712a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 722a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org def handle_starttag(self, tag, attrs): 732a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Overrides the HTMLParser method to implement functionality. 742a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 752a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[begin standard library documentation]] 762a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org This method is called to handle the start of a tag 772a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org (e.g. <div id="main">). 782a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 792a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org The tag argument is the name of the tag converted to lower 802a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org case. The attrs argument is a list of (name, value) pairs 812a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org containing the attributes found inside the tag's <> 822a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org brackets. The name will be translated to lower case, and 832a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org quotes in the value have been removed, and character and 842a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org entity references have been replaced. 852a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 862a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org For instance, for the tag <A HREF="http://www.cwi.nl/">, this 872a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org method would be called as handle_starttag('a', [('href', 882a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 'http://www.cwi.nl/')]). 892a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[end standard library documentation]] 90517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org """ 912a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org attrs = dict(attrs) 922a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if tag == 'div': 932a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # We are looking for <div id="tryjobdiv*">. 942a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org id_attr = attrs.get('id','') 952a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if id_attr.startswith('tryjobdiv'): 962a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._id = id_attr 972a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if (self._id and tag == 'a' 982a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org and 'build-result' in attrs.get('class', '').split()): 992a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # If we are already inside a <div id="tryjobdiv*">, we 1002a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # look for a link if the form 1012a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # <a class="build-result" href="*">. Then we save the 1022a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # (non-standard) status attribute and the URL. 1032a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._status = attrs.get('status') 1042a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._href = attrs.get('href') 1052a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._currently_parsing_trybotdiv = True 1062a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # Start saving anchor data. 1072a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 1082a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org def handle_data(self, data): 1092a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Overrides the HTMLParser method to implement functionality. 1102a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 1112a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[begin standard library documentation]] 1122a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org This method is called to process arbitrary data (e.g. text 1132a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org nodes and the content of <script>...</script> and 1142a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org <style>...</style>). 1152a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[end standard library documentation]] 1162a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """ 1172a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # Save the text inside the <a></a> tags. Assume <a> tags 1182a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # aren't nested. 1192a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if self._currently_parsing_trybotdiv: 1202a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._anchor_data += data 1212a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 1222a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org def handle_endtag(self, tag): 1232a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Overrides the HTMLParser method to implement functionality. 1242a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 1252a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[begin standard library documentation]] 1262a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org This method is called to handle the end tag of an element 1272a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org (e.g. </div>). The tag argument is the name of the tag 1282a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org converted to lower case. 1292a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[end standard library documentation]] 1302a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """ 1312a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if tag == 'a' and self._status: 1322a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # We take the accumulated self._anchor_data and save it as 1332a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # the bot name. 1342a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org bot = self._anchor_data.strip() 1352a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org stat = CodeReviewHTMLParser.Status(status=self._status, 1362a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org url=self._href) 1372a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if bot: 1382a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # Add to accumulating dictionary. 1392a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self.statuses[bot] = stat 1402a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # Reset state to search for the next bot. 1412a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._currently_parsing_trybotdiv = False 1422a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._anchor_data = '' 1432a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._status = None 1442a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._href = None 145517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 146517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 147517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgclass BuilderHTMLParser(HTMLParser.HTMLParser): 1482a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """parses Trybot web pages. 149517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 1502a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org Use the BuilderHTMLParser.parse static function to make use of 1512a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org this class. 152517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 1532a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org This uses the HTMLParser class because it's the best thing in 1542a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org Python's standard library. We need a little more power than a 1552a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org regex. [Search for "You can't parse [X]HTML with regex." for more 1562a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org information. 1572a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """ 1582a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # pylint: disable=I0011,R0904 1592a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org @staticmethod 1602a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org def parse(url): 1612a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Parses a Trybot web page. 162517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 1632a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org Args: 1642a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org url (string), a trybot result URL. 165517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 1662a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org Returns: 1672a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org An array of BuilderHTMLParser.Results, each a description 1682a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org of failure results, along with an optional url 169517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org """ 1702a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org parser = BuilderHTMLParser() 1712a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org try: 1722a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org parser.feed(urllib2.urlopen(url).read()) 1732a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org except (urllib2.URLError,): 1742a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org print >> sys.stderr, 'Error getting', url 1752a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org return [] 1762a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org parser.close() 1772a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org return parser.failure_results 1782a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 1792a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org Result = collections.namedtuple('Result', ['text', 'url']) 1802a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 1812a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org def __init__(self): 1822a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org HTMLParser.HTMLParser.__init__(self) 1832a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self.failure_results = [] 1842a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._current_failure_result = None 1852a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._divlevel = None 1862a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._li_level = 0 1872a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._li_data = '' 1882a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._current_failure = False 1892a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._failure_results_url = '' 1902a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 1912a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org def handle_starttag(self, tag, attrs): 1922a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Overrides the HTMLParser method to implement functionality. 1932a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 1942a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[begin standard library documentation]] 1952a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org This method is called to handle the start of a tag 1962a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org (e.g. <div id="main">). 1972a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 1982a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org The tag argument is the name of the tag converted to lower 1992a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org case. The attrs argument is a list of (name, value) pairs 2002a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org containing the attributes found inside the tag's <> 2012a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org brackets. The name will be translated to lower case, and 2022a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org quotes in the value have been removed, and character and 2032a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org entity references have been replaced. 2042a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 2052a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org For instance, for the tag <A HREF="http://www.cwi.nl/">, this 2062a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org method would be called as handle_starttag('a', [('href', 2072a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 'http://www.cwi.nl/')]). 2082a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[end standard library documentation]] 2092a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """ 2102a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org attrs = dict(attrs) 2112a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if tag == 'li': 2122a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # <li> tags can be nested. So we have to count the 2132a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # nest-level for backing out. 2142a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._li_level += 1 2152a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org return 2162a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if tag == 'div' and attrs.get('class') == 'failure result': 2172a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # We care about this sort of thing: 2182a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # <li> 2192a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # <li> 2202a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # <li> 2212a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # <div class="failure result">...</div> 2222a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # </li> 2232a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # </li> 2242a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # We want this text here. 2252a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # </li> 2262a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if self._li_level > 0: 2272a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._current_failure = True # Tells us to keep text. 2282a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org return 2292a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 2302a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if tag == 'a' and self._current_failure: 2312a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org href = attrs.get('href') 2322a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # Sometimes we want to keep the stdio url. We always 2332a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # return it, just in case. 2342a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if href.endswith('/logs/stdio'): 2352a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._failure_results_url = href 2362a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 2372a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org def handle_data(self, data): 2382a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Overrides the HTMLParser method to implement functionality. 2392a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 2402a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[begin standard library documentation]] 2412a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org This method is called to process arbitrary data (e.g. text 2422a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org nodes and the content of <script>...</script> and 2432a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org <style>...</style>). 2442a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[end standard library documentation]] 2452a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """ 2462a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if self._current_failure: 2472a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._li_data += data 248517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 2492a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org def handle_endtag(self, tag): 2502a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Overrides the HTMLParser method to implement functionality. 251517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 2522a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[begin standard library documentation]] 2532a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org This method is called to handle the end tag of an element 2542a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org (e.g. </div>). The tag argument is the name of the tag 2552a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org converted to lower case. 2562a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [[end standard library documentation]] 2572a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """ 2582a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if tag == 'li': 2592a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._li_level -= 1 2602a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if 0 == self._li_level: 2612a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if self._current_failure: 2622a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org result = self._li_data.strip() 2632a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org first = result.split()[0] 2642a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if first: 2652a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org result = re.sub( 2662a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org r'^%s(\s+%s)+' % (first, first), first, result) 2672a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # Sometimes, it repeats the same thing 2682a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # multiple times. 2692a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org result = re.sub(r'unexpected flaky.*', '', result) 2702a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # Remove some extra unnecessary text. 2712a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org result = re.sub(r'\bpreamble\b', '', result) 2722a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org result = re.sub(r'\bstdio\b', '', result) 2732a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org url = self._failure_results_url 2742a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self.failure_results.append( 2752a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org BuilderHTMLParser.Result(result, url)) 2762a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._current_failure_result = None 2772a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # Reset the state. 2782a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._current_failure = False 2792a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._li_data = '' 2802a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org self._failure_results_url = '' 281517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 282517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 2832a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.orgdef printer(indent, string): 2842a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Print indented, wrapped text. 2852a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """ 2862a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org def wrap_to(line, columns): 2872a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Wrap a line to the given number of columns, return a list 2882a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org of strings. 289517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org """ 2902a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org ret = [] 2912a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org nextline = '' 2922a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org for word in line.split(): 2932a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if nextline: 2942a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if len(nextline) + 1 + len(word) > columns: 2952a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org ret.append(nextline) 2962a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org nextline = word 2972a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org else: 2982a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org nextline += (' ' + word) 2992a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org else: 3002a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org nextline = word 3012a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if nextline: 3022a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org ret.append(nextline) 3032a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org return ret 3042a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out = sys.stdout 3052a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org spacer = ' ' 3062a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org for line in string.split('\n'): 3072a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org for i, wrapped_line in enumerate(wrap_to(line, 68 - (2 * indent))): 3082a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out.write(spacer * indent) 3092a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if i > 0: 3102a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out.write(spacer) 3112a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out.write(wrapped_line) 3122a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out.write('\n') 3132a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out.flush() 314517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 315517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 3162a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.orgdef main(control_url, roll_url, verbosity=1): 3172a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """Compare two Codereview URLs 3182a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 3192a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org Args: 3202a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org control_url, roll_url: (strings) URL of the format 3212a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org https://codereview.chromium.org/????????? 3222a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 3232a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org verbosity: (int) verbose level. 0, 1, or 2. 3242a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org """ 3252a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # pylint: disable=I0011,R0914,R0912 3262a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org control = CodeReviewHTMLParser.parse(control_url) 3272a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org roll = CodeReviewHTMLParser.parse(roll_url) 3282a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org all_bots = set(control) & set(roll) # Set intersection. 3292a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if not all_bots: 3302a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org print >> sys.stderr, ( 3312a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 'Error: control %s and roll %s have no common trybots.' 3322a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org % (list(control), list(roll))) 3332a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org return 3342a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 3352a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org control_name = '[control %s]' % control_url.split('/')[-1] 3362a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org roll_name = '[roll %s]' % roll_url.split('/')[-1] 3372a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 3382a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out = sys.stdout 3392a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 3402a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org for bot in sorted(all_bots): 3412a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if (roll[bot].status == 'success'): 3422a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if verbosity > 1: 343517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org printer(0, '==%s==' % bot) 3442a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org printer(1, 'OK') 3452a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org continue 346517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 3472a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if control[bot].status != 'failure' and roll[bot].status != 'failure': 3482a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org continue 3492a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org printer(0, '==%s==' % bot) 3502a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 3512a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org formatted_results = [] 3522a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org for (status, name, url) in [ 353517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org (control[bot].status, control_name, control[bot].url), 3542a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org ( roll[bot].status, roll_name, roll[bot].url)]: 3552a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org lines = [] 3562a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if status == 'failure': 3572a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org results = BuilderHTMLParser.parse(url) 3582a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org for result in results: 3592a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org formatted_result = re.sub(r'(\S*\.html) ', '\n__\g<1>\n', result.text) 3602a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # Strip runtimes. 3612a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org formatted_result = re.sub(r'\(.*\)', '', formatted_result) 3622a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org lines.append((2, formatted_result)) 3632a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if ('compile' in result.text or '...and more' in result.text): 3642a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org lines.append((3, re.sub('/[^/]*$', '/', url) + result.url)) 3652a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org formatted_results.append(lines) 3662a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 3672a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org identical = formatted_results[0] == formatted_results[1] 3682a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 3692a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 3702a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org for (formatted_result, (status, name, url)) in zip( 3712a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org formatted_results, 3722a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org [(control[bot].status, control_name, control[bot].url), 3732a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org (roll[bot].status, roll_name, roll[bot].url)]): 3742a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if status != 'failure' and not identical: 3752a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org printer(1, name) 3762a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org printer(2, status) 3772a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org elif status == 'failure': 3782a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if identical: 3792a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org printer(1, control_name + ' and ' + roll_name + ' failed identically') 3802a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org else: 3812a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org printer(1, name) 3822a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org for (indent, line) in formatted_result: 3832a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org printer(indent, line) 3842a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if identical: 3852a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org break 3862a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out.write('\n') 3872a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 3882a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if verbosity > 0: 3892a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org # Print out summary of all of the bots. 3902a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out.write('%11s %11s %4s %s\n\n' % 3912a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org ('CONTROL', 'ROLL', 'DIFF', 'BOT')) 3922a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org for bot in sorted(all_bots): 3932a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if roll[bot].status == 'success': 3942a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org diff = '' 3952a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org elif (control[bot].status == 'success' and 3962a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org roll[bot].status == 'failure'): 3972a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org diff = '!!!!' 3982a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org elif ('pending' in control[bot].status or 3992a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org 'pending' in roll[bot].status): 4002a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org diff = '....' 4012a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org else: 4022a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org diff = '****' 4032a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out.write('%11s %11s %4s %s\n' % ( 4042a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org control[bot].status, roll[bot].status, diff, bot)) 4052a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out.write('\n') 4062a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org out.flush() 407517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 408517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.orgif __name__ == '__main__': 4092a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org if len(sys.argv) < 3: 4102a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org print >> sys.stderr, __doc__ 4112a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org exit(1) 4122a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org main(sys.argv[1], sys.argv[2], 4132a1704f362faf03e899dbe86a269e224b8b5b29fcommit-bot@chromium.org int(os.environ.get('COMPARE_CODEREVIEW_VERBOSITY', 1))) 414517c1e2921bc20b8600061aa21a77a8810db597ecommit-bot@chromium.org 415