def parse_tag(line, extra_tags=[]): if not line: return None i = 0 if not is_capital(line[i]): return None i += 1 while i < len(line) and (is_capital(line[i]) or is_lower(line[i]) or line[i] == "-"): i += 1 if i == len(line) or line[i] != ":": return None key = format_tag_name(line[0:i]) value = line[i + 1 :].strip() if key not in (config.get_email_tags() + extra_tags) or not value: return None return {key: [value]}
def parse_tag(line, extra_tags=[]): if not line: return None i = 0 if not is_capital(line[i]): return None i += 1 while i < len(line) and (is_capital(line[i]) or is_lower(line[i]) or line[i] == '-'): i += 1 if i == len(line) or line[i] != ':': return None key = format_tag_name(line[0:i]) value = line[i + 1:].strip() if key not in (config.get_email_tags() + extra_tags) or not value: return None return { key: [value] }
def add_tags(message, tags): lines = [] payload = get_payload(message) in_sob = False done = False whitespace = [] for line in payload.split("\n"): # if we've added our tags, we're done if done: lines.append(line) continue # is this line a tag tag = parse_tag(line, config.get_email_tags()) if not in_sob and tag: in_sob = True if in_sob: # if it's a blank line, queue it for now if not line.strip(): whitespace.append(line) continue if tag: key = tag.keys()[0] value = tag[key] # always drop message-id tags if key == "Message-id": continue # if we hit a tag and there's whitespace before the tag, preserve it if whitespace: lines += whitespace whitespace = [] lines.append(line) # Don't duplicate tags if key in tags and value[0] in tags[key]: tags[key] = list(set(tags[key]) - set(value)) else: # we hit a non-blank line that isn't a tag done = True in_sob = False # append our tags before this line for key in tags: for val in tags[key]: if val: lines.append("%s: %s" % (key, val)) mid = message.get_message_id() if mid: lines.append("Message-id: %s" % mid) # but before any whitespace preceeding this line if whitespace: lines += whitespace whitespace = [] lines.append(line) else: lines.append(line) return "\n".join(lines)
def eval_query_term(series, term, scope): if term.find(':') != -1: command, args = term.split(':', 1) else: command = None if command == 'status': status = args.lower() if status == 'broken': return is_broken(series) elif status == 'obsolete': return is_obsolete(series) elif status == 'pull-request': return is_pull_request(series) elif status == 'rfc': return is_rfc(series) elif status == 'committed': return is_committed(series) elif status == 'reviewed': return is_reviewed(series) else: raise Exception("Unknown status `%s'" % status) elif command == 'label': txt = config.get_label(args) if txt == None: raise Exception('Invalid label %s' % args) tks = tokenize_query(txt) t, _ = parse_query(tks) return eval_query(series, t, scope) elif command == 'from': def fn(msg): return match_email_address(msg['from'], args) return eval_messages(series, fn, scope) elif command == 'committer': def fn(msg): if 'pull-request' in msg and 'commit' in msg['pull-request']: ret = match_email_address(msg['pull-request']['commit']['committer'], args) return ret elif 'committer' in msg: return match_email_address(msg['committer'], args) return False return eval_messages(series, fn, scope, cover=False) elif command == 'to': def fn(msg): for to in msg['to'] + msg['cc']: if match_email_address(to, args): return True return False return eval_messages(series, fn, scope) elif command == 'id': def fn(msg): return msg['message-id'] == args return eval_messages(series, fn, scope) elif command == 'tag': def fn(msg): if not args: return 'subject-tags' in msg return 'subject-tags' in msg and args.upper() in msg['subject-tags'] return eval_messages(series, fn, scope) elif command == 'release': def fn(msg): return 'for-release' in msg and msg['for-release'] == args return eval_messages(series, fn, scope) elif command and command.startswith('buildbot['): name = command[9:].split(']', 1)[0] if 'buildbots' in series and name in series['buildbots']: bot = series['buildbots'][name] steps = bot['steps'] item = args fail = False if item[0] == '+': item = item[1:] elif item[0] == '-': item = item[1:] fail = True if item == 'status': if fail: return bool(bot['status']) else: return bool(not bot['status']) for step, status, output in steps: if step == item: if fail: return bool(status) else: return bool(not status) return False elif command != None: command = message.format_tag_name(command) email_tags = config.get_email_tags() def fn(msg): if command not in msg['tags']: return False if not args: return True if command in email_tags: for addr in msg['tags'][command]: if match_flat_email_address(addr, args): return True return False return args in msg['tags'][command] return eval_messages(series, fn, scope, cover=False) else: def fn(msg): return msg['subject'].lower().find(term.lower()) != -1 return eval_messages(series, fn, scope)
def add_tags(message, tags): lines = [] payload = get_payload(message) in_sob = False done = False whitespace = [] for line in payload.split('\n'): # if we've added our tags, we're done if done: lines.append(line) continue # is this line a tag tag = parse_tag(line, config.get_email_tags()) if not in_sob and tag: in_sob = True if in_sob: # if it's a blank line, queue it for now if not line.strip(): whitespace.append(line) continue if tag: key = tag.keys()[0] value = tag[key] # always drop message-id tags if key == 'Message-id': continue # if we hit a tag and there's whitespace before the tag, preserve it if whitespace: lines += whitespace whitespace = [] lines.append(line) # Don't duplicate tags if key in tags and value[0] in tags[key]: tags[key] = list(set(tags[key]) - set(value)) else: # we hit a non-blank line that isn't a tag done = True in_sob = False # append our tags before this line for key in tags: for val in tags[key]: if val: lines.append('%s: %s' % (key, val)) mid = message.get_message_id() if mid: lines.append('Message-id: %s' % mid) # but before any whitespace preceeding this line if whitespace: lines += whitespace whitespace = [] lines.append(line) else: lines.append(line) return '\n'.join(lines)
def eval_query_term(series, term, scope): if term.find(':') != -1: command, args = term.split(':', 1) else: command = None if command == 'status': status = args.lower() if status == 'broken': return is_broken(series) elif status == 'obsolete': return is_obsolete(series) elif status == 'pull-request': return is_pull_request(series) elif status == 'rfc': return is_rfc(series) elif status == 'unapplied': return not (is_broken(series) or is_obsolete(series) or is_pull_request(series) or is_rfc(series) or is_committed(series) or is_applied(series)) elif status == 'committed': return is_committed(series) elif status == 'reviewed': return is_reviewed(series) elif status == 'applied': return is_applied(series) else: raise Exception("Unknown status `%s'" % status) elif command == 'label': txt = config.get_label(args) if txt == None: raise Exception('Invalid label %s' % args) tks = tokenize_query(txt) t, _ = parse_query(tks) return eval_query(series, t, scope) elif command == 'from': def fn(msg): return match_email_address(msg['from'], args) return eval_messages(series, fn, scope) elif command == 'committer': def fn(msg): if 'pull-request' in msg and 'commit' in msg['pull-request']: ret = match_email_address(msg['pull-request']['commit']['committer'], args) return ret elif 'committer' in msg: return match_email_address(msg['committer'], args) return False return eval_messages(series, fn, scope, cover=False) elif command == 'to': def fn(msg): for to in msg['to'] + msg['cc']: if match_email_address(to, args): return True return False return eval_messages(series, fn, scope) elif command == 'id': def fn(msg): return msg['message-id'] == args return eval_messages(series, fn, scope) elif command == 'tag': def fn(msg): if not args: return 'subject-tags' in msg return 'subject-tags' in msg and args.upper() in msg['subject-tags'] return eval_messages(series, fn, scope) elif command == 'release': def fn(msg): return 'for-release' in msg and msg['for-release'] == args return eval_messages(series, fn, scope) elif command and command.startswith('buildbot['): name = command[9:].split(']', 1)[0] if 'buildbots' in series and name in series['buildbots']: bot = series['buildbots'][name] steps = bot['steps'] item = args fail = False if item[0] == '+': item = item[1:] elif item[0] == '-': item = item[1:] fail = True if item == 'status': if fail: return bool(bot['status']) else: return bool(not bot['status']) for step, status, output in steps: if step == item: if fail: return bool(status) else: return bool(not status) return False elif command != None: command = message.format_tag_name(command) email_tags = config.get_email_tags() def fn(msg): if command not in msg['tags']: return False if not args: return True if command in email_tags: for addr in msg['tags'][command]: if match_flat_email_address(addr, args): return True return False return args in msg['tags'][command] return eval_messages(series, fn, scope, cover=False) else: def fn(msg): return msg['subject'].lower().find(term.lower()) != -1 return eval_messages(series, fn, scope)