1ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao"""Methods for reporting bugs.""" 2ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 3ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoimport subprocess, sys, os 4ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 5ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao__all__ = ['ReportFailure', 'BugReport', 'getReporters'] 6ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 7ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# 8ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 9ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoclass ReportFailure(Exception): 10ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao """Generic exception for failures in bug reporting.""" 11ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def __init__(self, value): 12ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao self.value = value 13ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 14ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# Collect information about a bug. 15ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 16ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoclass BugReport: 17ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def __init__(self, title, description, files): 18ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao self.title = title 19ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao self.description = description 20ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao self.files = files 21ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 22ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# Reporter interfaces. 23ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 24ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoimport os 25ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 26ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoimport email, mimetypes, smtplib 27ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaofrom email import encoders 28ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaofrom email.message import Message 29ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaofrom email.mime.base import MIMEBase 30ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaofrom email.mime.multipart import MIMEMultipart 31ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaofrom email.mime.text import MIMEText 32ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 33ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#===------------------------------------------------------------------------===# 34ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# ReporterParameter 35ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#===------------------------------------------------------------------------===# 36ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 37ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoclass ReporterParameter: 38ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def __init__(self, n): 39ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao self.name = n 40ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def getName(self): 41ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return self.name 42ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def getValue(self,r,bugtype,getConfigOption): 43ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return getConfigOption(r.getName(),self.getName()) 44ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def saveConfigValue(self): 45ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return True 46ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 47ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoclass TextParameter (ReporterParameter): 48ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def getHTML(self,r,bugtype,getConfigOption): 49ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return """\ 50ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao<tr> 51ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao<td class="form_clabel">%s:</td> 52ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao<td class="form_value"><input type="text" name="%s_%s" value="%s"></td> 53ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao</tr>"""%(self.getName(),r.getName(),self.getName(),self.getValue(r,bugtype,getConfigOption)) 54ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 55ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoclass SelectionParameter (ReporterParameter): 56ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def __init__(self, n, values): 57ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao ReporterParameter.__init__(self,n) 58ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao self.values = values 59ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 60ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def getHTML(self,r,bugtype,getConfigOption): 61ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao default = self.getValue(r,bugtype,getConfigOption) 62ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return """\ 63ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao<tr> 64ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao<td class="form_clabel">%s:</td><td class="form_value"><select name="%s_%s"> 65ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao%s 66ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao</select></td>"""%(self.getName(),r.getName(),self.getName(),'\n'.join(["""\ 67ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao<option value="%s"%s>%s</option>"""%(o[0], 68ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao o[0] == default and ' selected="selected"' or '', 69ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao o[1]) for o in self.values])) 70ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 71ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#===------------------------------------------------------------------------===# 72ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# Reporters 73ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#===------------------------------------------------------------------------===# 74ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 75ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoclass EmailReporter: 76ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def getName(self): 77ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return 'Email' 78ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 79ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def getParameters(self): 80ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return map(lambda x:TextParameter(x),['To', 'From', 'SMTP Server', 'SMTP Port']) 81ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 82ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # Lifted from python email module examples. 83ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def attachFile(self, outer, path): 84ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # Guess the content type based on the file's extension. Encoding 85ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # will be ignored, although we should check for simple things like 86ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # gzip'd or compressed files. 87ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao ctype, encoding = mimetypes.guess_type(path) 88ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if ctype is None or encoding is not None: 89ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # No guess could be made, or the file is encoded (compressed), so 90ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # use a generic bag-of-bits type. 91ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao ctype = 'application/octet-stream' 92ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao maintype, subtype = ctype.split('/', 1) 93ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if maintype == 'text': 94ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao fp = open(path) 95ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # Note: we should handle calculating the charset 96ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao msg = MIMEText(fp.read(), _subtype=subtype) 97ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao fp.close() 98ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao else: 99ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao fp = open(path, 'rb') 100ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao msg = MIMEBase(maintype, subtype) 101ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao msg.set_payload(fp.read()) 102ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao fp.close() 103ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # Encode the payload using Base64 104ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao encoders.encode_base64(msg) 105ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # Set the filename parameter 106ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao msg.add_header('Content-Disposition', 'attachment', filename=os.path.basename(path)) 107ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao outer.attach(msg) 108ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 109ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def fileReport(self, report, parameters): 110ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao mainMsg = """\ 111ea285162342df160e7860e26528bc7110bc6c0cdShih-wei LiaoBUG REPORT 112ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao--- 113ea285162342df160e7860e26528bc7110bc6c0cdShih-wei LiaoTitle: %s 114ea285162342df160e7860e26528bc7110bc6c0cdShih-wei LiaoDescription: %s 115ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao"""%(report.title, report.description) 116ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 117ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if not parameters.get('To'): 118ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao raise ReportFailure('No "To" address specified.') 119ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if not parameters.get('From'): 120ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao raise ReportFailure('No "From" address specified.') 121ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 122ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao msg = MIMEMultipart() 123ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao msg['Subject'] = 'BUG REPORT: %s'%(report.title) 124ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # FIXME: Get config parameters 125ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao msg['To'] = parameters.get('To') 126ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao msg['From'] = parameters.get('From') 127ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao msg.preamble = mainMsg 128ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 129ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao msg.attach(MIMEText(mainMsg, _subtype='text/plain')) 130ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao for file in report.files: 131ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao self.attachFile(msg, file) 132ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 133ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao try: 134ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao s = smtplib.SMTP(host=parameters.get('SMTP Server'), 135ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao port=parameters.get('SMTP Port')) 136ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao s.sendmail(msg['From'], msg['To'], msg.as_string()) 137ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao s.close() 138ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao except: 139ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao raise ReportFailure('Unable to send message via SMTP.') 140ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 141ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return "Message sent!" 142ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 143ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoclass BugzillaReporter: 144ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def getName(self): 145ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return 'Bugzilla' 146ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 147ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def getParameters(self): 148ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return map(lambda x:TextParameter(x),['URL','Product']) 149ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 150ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def fileReport(self, report, parameters): 151ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao raise NotImplementedError 152ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 153ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 154ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoclass RadarClassificationParameter(SelectionParameter): 155ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def __init__(self): 156ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao SelectionParameter.__init__(self,"Classification", 157ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao [['1', 'Security'], ['2', 'Crash/Hang/Data Loss'], 158ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao ['3', 'Performance'], ['4', 'UI/Usability'], 159ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao ['6', 'Serious Bug'], ['7', 'Other']]) 160ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 161ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def saveConfigValue(self): 162ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return False 163ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 164ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def getValue(self,r,bugtype,getConfigOption): 165ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if bugtype.find("leak") != -1: 166ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return '3' 167ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao elif bugtype.find("dereference") != -1: 168ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return '2' 169ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao elif bugtype.find("missing ivar release") != -1: 170ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return '3' 171ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao else: 172ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return '7' 173ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 174ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoclass RadarReporter: 175ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao @staticmethod 176ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def isAvailable(): 177ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # FIXME: Find this .scpt better 178ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao path = os.path.join(os.path.dirname(__file__),'Resources/GetRadarVersion.scpt') 179ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao try: 180ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao p = subprocess.Popen(['osascript',path], 181ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao stdout=subprocess.PIPE, stderr=subprocess.PIPE) 182ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao except: 183ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return False 184ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao data,err = p.communicate() 185ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao res = p.wait() 186ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # FIXME: Check version? Check for no errors? 187ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return res == 0 188ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 189ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def getName(self): 190ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return 'Radar' 191ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 192ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def getParameters(self): 193ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return [ TextParameter('Component'), TextParameter('Component Version'), 194ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao RadarClassificationParameter() ] 195ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 196ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao def fileReport(self, report, parameters): 197ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao component = parameters.get('Component', '') 198ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao componentVersion = parameters.get('Component Version', '') 199ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao classification = parameters.get('Classification', '') 200ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao personID = "" 201ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao diagnosis = "" 202ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao config = "" 203ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 204ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if not component.strip(): 205ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao component = 'Bugs found by clang Analyzer' 206ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if not componentVersion.strip(): 207ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao componentVersion = 'X' 208ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 209ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao script = os.path.join(os.path.dirname(__file__),'Resources/FileRadar.scpt') 210ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao args = ['osascript', script, component, componentVersion, classification, personID, report.title, 211ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao report.description, diagnosis, config] + map(os.path.abspath, report.files) 212ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# print >>sys.stderr, args 213ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao try: 214ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 215ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao except: 216ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao raise ReportFailure("Unable to file radar (AppleScript failure).") 217ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao data, err = p.communicate() 218ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao res = p.wait() 219ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 220ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if res: 221ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao raise ReportFailure("Unable to file radar (AppleScript failure).") 222ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 223ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao try: 224ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao values = eval(data) 225ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao except: 226ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao raise ReportFailure("Unable to process radar results.") 227ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 228ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # We expect (int: bugID, str: message) 229ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if len(values) != 2 or not isinstance(values[0], int): 230ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao raise ReportFailure("Unable to process radar results.") 231ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 232ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao bugID,message = values 233ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao bugID = int(bugID) 234ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 235ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if not bugID: 236ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao raise ReportFailure(message) 237ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 238ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return "Filed: <a href=\"rdar://%d/\">%d</a>"%(bugID,bugID) 239ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 240ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao### 241ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 242ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodef getReporters(): 243ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao reporters = [] 244ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if RadarReporter.isAvailable(): 245ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao reporters.append(RadarReporter()) 246ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao reporters.append(EmailReporter()) 247ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return reporters 248ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 249