logs.py

来自「The BuildBot is a system to automate the」· Python 代码 · 共 172 行

PY
172
字号
from zope.interface import implementsfrom twisted.python import componentsfrom twisted.spread import pbfrom twisted.web import html, serverfrom twisted.web.resource import Resourcefrom twisted.web.error import NoResourcefrom buildbot import interfacesfrom buildbot.status import builderfrom buildbot.status.web.base import IHTMLLog, HtmlResourcetextlog_stylesheet = """<style type="text/css"> div.data {  font-family: "Courier New", courier, monotype; } span.stdout {  font-family: "Courier New", courier, monotype; } span.stderr {  font-family: "Courier New", courier, monotype;  color: red; } span.header {  font-family: "Courier New", courier, monotype;  color: blue; }</style>"""class ChunkConsumer:    implements(interfaces.IStatusLogConsumer)    def __init__(self, original, textlog):        self.original = original        self.textlog = textlog    def registerProducer(self, producer, streaming):        self.producer = producer        self.original.registerProducer(producer, streaming)    def unregisterProducer(self):        self.original.unregisterProducer()    def writeChunk(self, chunk):        formatted = self.textlog.content([chunk])        try:            self.original.write(formatted)        except pb.DeadReferenceError:            self.producing.stopProducing()    def finish(self):        self.textlog.finished()# /builders/$builder/builds/$buildnum/steps/$stepname/logs/$lognameclass TextLog(Resource):    # a new instance of this Resource is created for each client who views    # it, so we can afford to track the request in the Resource.    implements(IHTMLLog)    asText = False    subscribed = False    def __init__(self, original):        Resource.__init__(self)        self.original = original    def getChild(self, path, req):        if path == "text":            self.asText = True            return self        return HtmlResource.getChild(self, path, req)    def htmlHeader(self, request):        title = "Log File contents"        data = "<html>\n<head><title>" + title + "</title>\n"        data += textlog_stylesheet        data += "</head>\n"        data += "<body vlink=\"#800080\">\n"        texturl = request.childLink("text")        data += '<a href="%s">(view as text)</a><br />\n' % texturl        data += "<pre>\n"        return data    def content(self, entries):        spanfmt = '<span class="%s">%s</span>'        data = ""        for type, entry in entries:            if type >= len(builder.ChunkTypes) or type < 0:                # non-std channel, don't display                continue            if self.asText:                if type != builder.HEADER:                    data += entry            else:                data += spanfmt % (builder.ChunkTypes[type],                                   html.escape(entry))        return data    def htmlFooter(self):        data = "</pre>\n"        data += "</body></html>\n"        return data    def render_HEAD(self, request):        if self.asText:            request.setHeader("content-type", "text/plain")        else:            request.setHeader("content-type", "text/html")        # vague approximation, ignores markup        request.setHeader("content-length", self.original.length)        return ''    def render_GET(self, req):        self.req = req        if self.asText:            req.setHeader("content-type", "text/plain")        else:            req.setHeader("content-type", "text/html")        if not self.asText:            req.write(self.htmlHeader(req))        self.original.subscribeConsumer(ChunkConsumer(req, self))        return server.NOT_DONE_YET    def finished(self):        if not self.req:            return        try:            if not self.asText:                self.req.write(self.htmlFooter())            self.req.finish()        except pb.DeadReferenceError:            pass        # break the cycle, the Request's .notifications list includes the        # Deferred (from req.notifyFinish) that's pointing at us.        self.req = Nonecomponents.registerAdapter(TextLog, interfaces.IStatusLog, IHTMLLog)class HTMLLog(Resource):    implements(IHTMLLog)    def __init__(self, original):        Resource.__init__(self)        self.original = original    def render(self, request):        request.setHeader("content-type", "text/html")        return self.original.htmlcomponents.registerAdapter(HTMLLog, builder.HTMLLogFile, IHTMLLog)class LogsResource(HtmlResource):    addSlash = True    def __init__(self, step_status):        HtmlResource.__init__(self)        self.step_status = step_status    def getChild(self, path, req):        for log in self.step_status.getLogs():            if path == log.getName():                if log.hasContents():                    return IHTMLLog(interfaces.IStatusLog(log))                return NoResource("Empty Log '%s'" % path)        return HtmlResource.getChild(self, path, req)

⌨️ 快捷键说明

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