def phase1(self, request, sourceNames, timestamps, eventGrid, sourceEvents): # phase1 rendering: table, but boxes do not overlap data = "" if not timestamps: return data lastDate = None for r in range(0, len(timestamps)): chunkstrip = eventGrid[r] # chunkstrip is a horizontal strip of event blocks. Each block # is a vertical list of events, all for the same source. assert (len(chunkstrip) == len(sourceNames)) maxRows = reduce(lambda x, y: max(x, y), map(lambda x: len(x), chunkstrip)) for i in range(maxRows): data += " <tr>\n" if i == 0: stuff = [] # add the date at the beginning, and each time it changes today = time.strftime("<b>%d %b %Y</b>", time.localtime(timestamps[r])) todayday = time.strftime("<b>%a</b>", time.localtime(timestamps[r])) if today != lastDate: stuff.append(todayday) stuff.append(today) lastDate = today stuff.append( time.strftime("%H:%M:%S", time.localtime(timestamps[r]))) data += td(stuff, valign="bottom", align="center", rowspan=maxRows, class_="Time") for c in range(0, len(chunkstrip)): block = chunkstrip[c] assert (block != None) # should be [] instead # bottom-justify offset = maxRows - len(block) if i < offset: data += td("") else: e = block[i - offset] box = IBox(e).getBox(request) box.parms["show_idle"] = 1 data += box.td(valign="top", align="center") data += " </tr>\n" return data
def phase1(self, request, sourceNames, timestamps, eventGrid, sourceEvents): # phase1 rendering: table, but boxes do not overlap data = "" if not timestamps: return data lastDate = None for r in range(0, len(timestamps)): chunkstrip = eventGrid[r] # chunkstrip is a horizontal strip of event blocks. Each block # is a vertical list of events, all for the same source. assert(len(chunkstrip) == len(sourceNames)) maxRows = reduce(lambda x,y: max(x,y), map(lambda x: len(x), chunkstrip)) for i in range(maxRows): data += " <tr>\n"; if i == 0: stuff = [] # add the date at the beginning, and each time it changes today = time.strftime("<b>%d %b %Y</b>", time.localtime(timestamps[r])) todayday = time.strftime("<b>%a</b>", time.localtime(timestamps[r])) if today != lastDate: stuff.append(todayday) stuff.append(today) lastDate = today stuff.append( time.strftime("%H:%M:%S", time.localtime(timestamps[r]))) data += td(stuff, valign="bottom", align="center", rowspan=maxRows, class_="Time") for c in range(0, len(chunkstrip)): block = chunkstrip[c] assert(block != None) # should be [] instead # bottom-justify offset = maxRows - len(block) if i < offset: data += td("") else: e = block[i-offset] box = IBox(e).getBox(request) box.parms["show_idle"] = 1 data += box.td(valign="top", align="center") data += " </tr>\n" return data
def phase2(self, request, sourceNames, timestamps, eventGrid, sourceEvents): data = "" if not timestamps: return data # first pass: figure out the height of the chunks, populate grid grid = [] for i in range(1 + len(sourceNames)): grid.append([]) # grid is a list of columns, one for the timestamps, and one per # event source. Each column is exactly the same height. Each element # of the list is a single <td> box. lastDate = time.strftime("<b>%d %b %Y</b>", time.localtime(util.now())) for r in range(0, len(timestamps)): chunkstrip = eventGrid[r] # chunkstrip is a horizontal strip of event blocks. Each block # is a vertical list of events, all for the same source. assert (len(chunkstrip) == len(sourceNames)) maxRows = reduce(lambda x, y: max(x, y), map(lambda x: len(x), chunkstrip)) for i in range(maxRows): if i != maxRows - 1: grid[0].append(None) else: # timestamp goes at the bottom of the chunk stuff = [] # add the date at the beginning (if it is not the same as # today's date), and each time it changes todayday = time.strftime("<b>%a</b>", time.localtime(timestamps[r])) today = time.strftime("<b>%d %b %Y</b>", time.localtime(timestamps[r])) if today != lastDate: stuff.append(todayday) stuff.append(today) lastDate = today stuff.append( time.strftime("%H:%M:%S", time.localtime(timestamps[r]))) grid[0].append( Box(text=stuff, class_="Time", valign="bottom", align="center")) # at this point the timestamp column has been populated with # maxRows boxes, most None but the last one has the time string for c in range(0, len(chunkstrip)): block = chunkstrip[c] assert (block != None) # should be [] instead for i in range(maxRows - len(block)): # fill top of chunk with blank space grid[c + 1].append(None) for i in range(len(block)): # so the events are bottom-justified b = IBox(block[i]).getBox(request) b.parms['valign'] = "top" b.parms['align'] = "center" grid[c + 1].append(b) # now all the other columns have maxRows new boxes too # populate the last row, if empty gridlen = len(grid[0]) for i in range(len(grid)): strip = grid[i] assert (len(strip) == gridlen) if strip[-1] == None: if sourceEvents[i - 1]: filler = IBox(sourceEvents[i - 1]).getBox(request) else: # this can happen if you delete part of the build history filler = Box(text=["?"], align="center") strip[-1] = filler strip[-1].parms['rowspan'] = 1 # second pass: bubble the events upwards to un-occupied locations # Every square of the grid that has a None in it needs to have # something else take its place. noBubble = request.args.get("nobubble", ['0']) noBubble = int(noBubble[0]) if not noBubble: for col in range(len(grid)): strip = grid[col] if col == 1: # changes are handled differently for i in range(2, len(strip) + 1): # only merge empty boxes. Don't bubble commit boxes. if strip[-i] == None: next = strip[-i + 1] assert (next) if next: #if not next.event: if next.spacer: # bubble the empty box up strip[-i] = next strip[-i].parms['rowspan'] += 1 strip[-i + 1] = None else: # we are above a commit box. Leave it # be, and turn the current box into an # empty one strip[-i] = Box([], rowspan=1, comment="commit bubble") strip[-i].spacer = True else: # we are above another empty box, which # somehow wasn't already converted. # Shouldn't happen pass else: for i in range(2, len(strip) + 1): # strip[-i] will go from next-to-last back to first if strip[-i] == None: # bubble previous item up assert (strip[-i + 1] != None) strip[-i] = strip[-i + 1] strip[-i].parms['rowspan'] += 1 strip[-i + 1] = None else: strip[-i].parms['rowspan'] = 1 # third pass: render the HTML table for i in range(gridlen): data += " <tr>\n" for strip in grid: b = strip[i] if b: data += b.td() else: if noBubble: data += td([]) # Nones are left empty, rowspan should make it all fit data += " </tr>\n" return data
def phase2(self, request, sourceNames, timestamps, eventGrid, sourceEvents): data = "" if not timestamps: return data # first pass: figure out the height of the chunks, populate grid grid = [] for i in range(1+len(sourceNames)): grid.append([]) # grid is a list of columns, one for the timestamps, and one per # event source. Each column is exactly the same height. Each element # of the list is a single <td> box. lastDate = time.strftime("<b>%d %b %Y</b>", time.localtime(util.now())) for r in range(0, len(timestamps)): chunkstrip = eventGrid[r] # chunkstrip is a horizontal strip of event blocks. Each block # is a vertical list of events, all for the same source. assert(len(chunkstrip) == len(sourceNames)) maxRows = reduce(lambda x,y: max(x,y), map(lambda x: len(x), chunkstrip)) for i in range(maxRows): if i != maxRows-1: grid[0].append(None) else: # timestamp goes at the bottom of the chunk stuff = [] # add the date at the beginning (if it is not the same as # today's date), and each time it changes todayday = time.strftime("<b>%a</b>", time.localtime(timestamps[r])) today = time.strftime("<b>%d %b %Y</b>", time.localtime(timestamps[r])) if today != lastDate: stuff.append(todayday) stuff.append(today) lastDate = today stuff.append( time.strftime("%H:%M:%S", time.localtime(timestamps[r]))) grid[0].append(Box(text=stuff, class_="Time", valign="bottom", align="center")) # at this point the timestamp column has been populated with # maxRows boxes, most None but the last one has the time string for c in range(0, len(chunkstrip)): block = chunkstrip[c] assert(block != None) # should be [] instead for i in range(maxRows - len(block)): # fill top of chunk with blank space grid[c+1].append(None) for i in range(len(block)): # so the events are bottom-justified b = IBox(block[i]).getBox(request) b.parms['valign'] = "top" b.parms['align'] = "center" grid[c+1].append(b) # now all the other columns have maxRows new boxes too # populate the last row, if empty gridlen = len(grid[0]) for i in range(len(grid)): strip = grid[i] assert(len(strip) == gridlen) if strip[-1] == None: if sourceEvents[i-1]: filler = IBox(sourceEvents[i-1]).getBox(request) else: # this can happen if you delete part of the build history filler = Box(text=["?"], align="center") strip[-1] = filler strip[-1].parms['rowspan'] = 1 # second pass: bubble the events upwards to un-occupied locations # Every square of the grid that has a None in it needs to have # something else take its place. noBubble = request.args.get("nobubble",['0']) noBubble = int(noBubble[0]) if not noBubble: for col in range(len(grid)): strip = grid[col] if col == 1: # changes are handled differently for i in range(2, len(strip)+1): # only merge empty boxes. Don't bubble commit boxes. if strip[-i] == None: next = strip[-i+1] assert(next) if next: #if not next.event: if next.spacer: # bubble the empty box up strip[-i] = next strip[-i].parms['rowspan'] += 1 strip[-i+1] = None else: # we are above a commit box. Leave it # be, and turn the current box into an # empty one strip[-i] = Box([], rowspan=1, comment="commit bubble") strip[-i].spacer = True else: # we are above another empty box, which # somehow wasn't already converted. # Shouldn't happen pass else: for i in range(2, len(strip)+1): # strip[-i] will go from next-to-last back to first if strip[-i] == None: # bubble previous item up assert(strip[-i+1] != None) strip[-i] = strip[-i+1] strip[-i].parms['rowspan'] += 1 strip[-i+1] = None else: strip[-i].parms['rowspan'] = 1 # third pass: render the HTML table for i in range(gridlen): data += " <tr>\n"; for strip in grid: b = strip[i] if b: # convert data to a unicode string, whacking any non-ASCII characters it might contain s = b.td() if isinstance(s, unicode): s = s.encode("utf-8", "replace") data += s else: if noBubble: data += td([]) # Nones are left empty, rowspan should make it all fit data += " </tr>\n" return data