📄 email_maintainers.py
字号:
## Copyright (C) 2005, 2007 The Trustees of Indiana University # Author: Douglas Gregor## Distributed under the Boost Software License, Version 1.0. (See# accompanying file LICENSE_1_0.txt or copy at# http://www.boost.org/LICENSE_1_0.txt)#import reimport smtplibimport osimport timeimport stringimport datetimeimport sysreport_author = "Douglas Gregor <dgregor@osl.iu.edu>"boost_dev_list = "Boost Developer List <boost@lists.boost.org>"def sorted_keys( dict ): result = dict.keys() result.sort() return resultclass Platform: """ All of the failures for a particular platform. """ def __init__(self, name): self.name = name self.failures = list() return def addFailure(self, failure): self.failures.append(failure) return def isBroken(self): return len(self.failures) > 300class Failure: """ A single test case failure in the report. """ def __init__(self, test, platform): self.test = test self.platform = platform returnclass Test: """ All of the failures for a single test name within a library. """ def __init__(self, library, name): self.library = library self.name = name self.failures = list() return def addFailure(self, failure): self.failures.append(failure) return def numFailures(self): return len(self.failures) def numReportableFailures(self): """ Returns the number of failures that we will report to the maintainers of the library. This doesn't count failures on broken platforms. """ count = 0 for failure in self.failures: if not failure.platform.isBroken(): count += 1 pass pass return countclass Library: """ All of the information about the failures in a single library. """ def __init__(self, name): self.name = name self.maintainers = list() self.tests = list() return def addTest(self, test): """ Add another test to the library. """ self.tests.append(test) return def addMaintainer(self, maintainer): """ Add a new maintainer for this library. """ self.maintainers.append(maintainer) return def numFailures(self): count = 0 for test in self.tests: count += test.numFailures() pass return count def numReportableFailures(self): count = 0 for test in self.tests: count += test.numReportableFailures() pass return countclass Maintainer: """ Information about the maintainer of a library """ def __init__(self, name, email): self.name = name self.email = email self.libraries = list() return def addLibrary(self, library): self.libraries.append(library) return def composeEmail(self, report): """ Composes an e-mail to this maintainer with information about the failures in his or her libraries, omitting those that come from "broken" platforms. Returns the e-mail text if a message needs to be sent, or None otherwise. """ # Determine if we need to send a message to this developer. requires_message = False for library in self.libraries: if library.numReportableFailures() > 0: requires_message = True break if not requires_message: return None # Build the message header message = """From: Douglas Gregor <dgregor@osl.iu.edu>To: """ message += self.name + ' <' + self.email + '>' message += """Reply-To: boost@lists.boost.orgSubject: Failures in your Boost libraries as of """ message += str(datetime.date.today()) + " [" + report.branch + "]" message += """You are receiving this report because one or more of the libraries youmaintain has regression test failures that are not accounted for.A full version of the report is sent to the Boost developer's mailinglist.Detailed report:""" message += ' ' + report.url + """There are failures in these libraries you maintain:""" # List the libraries this maintainer is responsible for and # the number of reportable failures in that library. for library in self.libraries: num_failures = library.numReportableFailures() if num_failures > 0: message += ' ' + library.name + ' (' + str(num_failures) + ')\n' pass pass # Provide the details for the failures in each library. for library in self.libraries: if library.numReportableFailures() > 0: message += '\n|' + library.name + '|\n' for test in library.tests: if test.numReportableFailures() > 0: message += ' ' + test.name + ':' for failure in test.failures: if not failure.platform.isBroken(): message += ' ' + failure.platform.name pass pass message += '\n' pass pass pass pass return messageclass Report: """ The complete report of all failing test cases. """ def __init__(self, branch = 'trunk'): self.branch = branch self.date = None self.url = None self.libraries = dict() self.platforms = dict() self.maintainers = dict() return def getPlatform(self, name): """ Retrieve the platform with the given name. """ if self.platforms.has_key(name): return self.platforms[name] else: self.platforms[name] = Platform(name) return self.platforms[name] def getMaintainer(self, name, email): """ Retrieve the maintainer with the given name and e-mail address. """ if self.maintainers.has_key(name): return self.maintainers[name] else: self.maintainers[name] = Maintainer(name, email) return self.maintainers[name] def parseIssuesEmail(self): """ Try to parse the issues e-mail file. Returns True if everything was successful, false otherwise. """ # See if we actually got the file if not os.path.isfile('issues-email.txt'): return False # Determine the set of libraries that have unresolved failures date_regex = re.compile('Report time: (.*)') url_regex = re.compile(' (http://.*)') library_regex = re.compile('\|(.*)\|') failure_regex = re.compile(' ([^:]*): (.*)') current_library = None for line in file('issues-email.txt', 'r'): # Check for the report time line m = date_regex.match(line) if m: self.date = m.group(1) continue # Check for the detailed report URL m = url_regex.match(line) if m: self.url = m.group(1) continue # Check for a library header m = library_regex.match(line) if m: current_library = Library(m.group(1)) self.libraries[m.group(1)] = current_library continue # Check for a library test and its failures m = failure_regex.match(line) if m: test = Test(current_library, m.group(1)) for platform_name in re.split('\s*', m.group(2)): if platform_name != '': platform = self.getPlatform(platform_name) failure = Failure(test, platform) test.addFailure(failure) platform.addFailure(failure) pass current_library.addTest(test) continue pass return True def getIssuesEmail(self): """ Retrieve the issues email from beta.boost.org, trying a few times in case something wonky is happening. If we can retrieve the file, calls parseIssuesEmail and return True; otherwise, return False. """ base_url = "http://beta.boost.org/development/tests/" base_url += self.branch base_url += "/developer/"; got_issues = False # Ping the server by looking for an HTML file print "Pinging the server to initiate extraction..." ping_url = base_url + "issues.html" os.system('curl -O ' + ping_url) os.system('rm -f issues.html') for x in range(30): # Update issues-email.txt url = base_url + "issues-email.txt" print 'Retrieving issues email from ' + url os.system('rm -f issues-email.txt') os.system('curl -O ' + url) if self.parseIssuesEmail(): return True print 'Failed to fetch issues email. '
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -