def showHistory(tasks, describeTask): if isinstance(tasks, Task): tasks = [tasks] revs = [task.getRevisions() for task in tasks] revs = [rev for l in revs for rev in l] # Flatten revs.sort(key = lambda rev: rev.timestamp) # Sort ascending by timestamp revMap = dict([((rev.id, rev.revision), rev) for rev in revs]) # Map (id, revision #) to the revision print "<div class=\"revision-history\">" fields = (set(Task.fields()) | set(['assigned'])) - set(['creatorid', 'timestamp', 'revision']) prevDay = None for rev in revs: day = date.fromtimestamp(rev.timestamp) if not prevDay or prevDay != day: print "<h2 class=\"daymarker\">%s</h2>" % day.strftime("%d %b %Y").lstrip('0') prevDay = day if rev.revision == 1: created(rev, None, describeTask) if rev.deleted: deleted(rev, None, describeTask) continue oldRev = revMap[(rev.id, rev.revision - 1)] changedFields = filter(lambda f: oldRev.__getattribute__(f) != rev.__getattribute__(f), fields) # If hours is the only changed field, output it. Otherwise it will be attached to the first change if 'hours' in changedFields: if changedFields == ['hours']: hoursChanged(rev, oldRev, describeTask) changedFields.remove('hours') for field in changedFields: if field == 'status': statusChanged(rev, oldRev, describeTask) elif field == 'name': renamed(rev, oldRev, describeTask) elif field == 'deleted': if rev.deleted: deleted(rev, oldRev, describeTask) else: undeleted(rev, oldRev, describeTask) elif field == 'assigned': reassigned(rev, oldRev, describeTask) elif field == 'assignedids': pass # Handled by 'assigned' elif field == 'goalid': goalChanged(rev, oldRev, describeTask) elif field == 'groupid': pass # Switching groups doesn't really matter else: unrecognizedChange(rev, oldRev, field, describeTask)