def produce_template(cls, constituents, subject, **config): """ Helper function used by `merge`. Produces the beginnings of a merged conglomerate message that needs to be later filled out by a subclass. """ def _extract_timestamp(msg): value = msg['timestamp'] if hasattr(value, 'timetuple'): value = time.mktime(value.timetuple()) return value N = len(constituents) timestamps = [_extract_timestamp(msg) for msg in constituents] average_timestamp = sum(timestamps) / N # Avoid circular import import fedmsg.meta as fm # Optional, so, avoid importing it at the topmost level import arrow usernames = set(sum([ list(fm.msg2usernames(msg, **config)) for msg in constituents], [])) packages = set(sum([ list(fm.msg2packages(msg, **config)) for msg in constituents], [])) topics = set([msg['topic'] for msg in constituents]) categories = set([t.split('.')[3] for t in topics]) # Include metadata about constituent messages in the aggregate # http://da.gd/12Eso msg_ids = dict([ (msg['msg_id'], { 'title': fm.msg2title(msg, **config), 'subtitle': fm.msg2subtitle(msg, **config), 'subjective': fm.msg2subjective(msg, subject=subject, **config), 'link': fm.msg2link(msg, **config), 'icon': fm.msg2icon(msg, **config), 'secondary_icon': fm.msg2secondary_icon(msg, **config), 'usernames': fm.msg2usernames(msg, **config), 'packages': fm.msg2packages(msg, **config), 'objects': fm.msg2objects(msg, **config), }) for msg in constituents]) return { 'start_time': min(timestamps), 'end_time': max(timestamps), 'timestamp': average_timestamp, 'human_time': arrow.get(average_timestamp).humanize(), 'msg_ids': msg_ids, 'usernames': usernames, 'packages': packages, 'topics': topics, 'categories': categories, 'icon': fm.msg2icon(constituents[0], **config), }