⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 waterfall.py

📁 The BuildBot is a system to automate the compile/test cycle required by most software projects. CVS
💻 PY
📖 第 1 页 / 共 3 页
字号:
        spanLength = 10  # ten-second chunks        maxPageLen = int(request.args.get("num_events", [200])[0])        # first step is to walk backwards in time, asking each column        # (commit, all builders) if they have any events there. Build up the        # array of events, and stop when we have a reasonable number.                    commit_source = self.getChangemaster(request)        lastEventTime = util.now()        sources = [commit_source] + builders        changeNames = ["changes"]        builderNames = map(lambda builder: builder.getName(), builders)        sourceNames = changeNames + builderNames        sourceEvents = []        sourceGenerators = []        def get_event_from(g):            try:                while True:                    e = g.next()                    # e might be builder.BuildStepStatus,                    # builder.BuildStatus, builder.Event,                    # waterfall.Spacer(builder.Event), or changes.Change .                    # The showEvents=False flag means we should hide                    # builder.Event .                    if not showEvents and isinstance(e, builder.Event):                        continue                    break                event = interfaces.IStatusEvent(e)                if debug:                    log.msg("gen %s gave1 %s" % (g, event.getText()))            except StopIteration:                event = None            return event        for s in sources:            gen = insertGaps(s.eventGenerator(filterBranches), lastEventTime)            sourceGenerators.append(gen)            # get the first event            sourceEvents.append(get_event_from(gen))        eventGrid = []        timestamps = []        lastEventTime = 0        for e in sourceEvents:            if e and e.getTimes()[0] > lastEventTime:                lastEventTime = e.getTimes()[0]        if lastEventTime == 0:            lastEventTime = util.now()        spanStart = lastEventTime - spanLength        debugGather = 0        while 1:            if debugGather: log.msg("checking (%s,]" % spanStart)            # the tableau of potential events is in sourceEvents[]. The            # window crawls backwards, and we examine one source at a time.            # If the source's top-most event is in the window, is it pushed            # onto the events[] array and the tableau is refilled. This            # continues until the tableau event is not in the window (or is            # missing).            spanEvents = [] # for all sources, in this span. row of eventGrid            firstTimestamp = None # timestamp of first event in the span            lastTimestamp = None # last pre-span event, for next span            for c in range(len(sourceGenerators)):                events = [] # for this source, in this span. cell of eventGrid                event = sourceEvents[c]                while event and spanStart < event.getTimes()[0]:                    # to look at windows that don't end with the present,                    # condition the .append on event.time <= spanFinish                    if not IBox(event, None):                        log.msg("BAD EVENT", event, event.getText())                        assert 0                    if debug:                        log.msg("pushing", event.getText(), event)                    events.append(event)                    starts, finishes = event.getTimes()                    firstTimestamp = util.earlier(firstTimestamp, starts)                    event = get_event_from(sourceGenerators[c])                if debug:                    log.msg("finished span")                if event:                    # this is the last pre-span event for this source                    lastTimestamp = util.later(lastTimestamp,                                               event.getTimes()[0])                if debugGather:                    log.msg(" got %s from %s" % (events, sourceNames[c]))                sourceEvents[c] = event # refill the tableau                spanEvents.append(events)            # only show events older than maxTime. This makes it possible to            # visit a page that shows what it would be like to scroll off the            # bottom of this one.            if firstTimestamp is not None and firstTimestamp <= maxTime:                eventGrid.append(spanEvents)                timestamps.append(firstTimestamp)            if lastTimestamp:                spanStart = lastTimestamp - spanLength            else:                # no more events                break            if minTime is not None and lastTimestamp < minTime:                break            if len(timestamps) > maxPageLen:                break                                    # now loop                    # loop is finished. now we have eventGrid[] and timestamps[]        if debugGather: log.msg("finished loop")        assert(len(timestamps) == len(eventGrid))        return (changeNames, builderNames, timestamps, eventGrid, sourceEvents)        def phase0(self, request, sourceNames, timestamps, eventGrid):        # phase0 rendering        if not timestamps:            return "no events"        data = ""        for r in range(0, len(timestamps)):            data += "<p>\n"            data += "[%s]<br />" % timestamps[r]            row = eventGrid[r]            assert(len(row) == len(sourceNames))            for c in range(0, len(row)):                if row[c]:                    data += "<b>%s</b><br />\n" % sourceNames[c]                    for e in row[c]:                        log.msg("Event", r, c, sourceNames[c], e.getText())                        lognames = [loog.getName() for loog in e.getLogs()]                        data += "%s: %s: %s<br />" % (e.getText(),                                                         e.getTimes()[0],                                                         lognames)                else:                    data += "<b>%s</b> [none]<br />\n" % sourceNames[c]        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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -