Package buildbot :: Package status :: Package web :: Module logs
[frames] | no frames]

Source Code for Module buildbot.status.web.logs

  1   
  2  from zope.interface import implements 
  3  from twisted.python import components 
  4  from twisted.spread import pb 
  5  from twisted.web import server 
  6  from twisted.web.resource import Resource 
  7  from twisted.web.error import NoResource 
  8   
  9  from buildbot import interfaces 
 10  from buildbot.status import builder 
 11  from buildbot.status.web.base import IHTMLLog, HtmlResource, path_to_root 
 12   
13 -class ChunkConsumer:
14 implements(interfaces.IStatusLogConsumer) 15
16 - def __init__(self, original, textlog):
17 self.original = original 18 self.textlog = textlog
19 - def registerProducer(self, producer, streaming):
20 self.producer = producer 21 self.original.registerProducer(producer, streaming)
22 - def unregisterProducer(self):
23 self.original.unregisterProducer()
24 - def writeChunk(self, chunk):
25 formatted = self.textlog.content([chunk]) 26 try: 27 if isinstance(formatted, unicode): 28 formatted = formatted.encode('utf-8') 29 self.original.write(formatted) 30 except pb.DeadReferenceError: 31 self.producing.stopProducing()
32 - def finish(self):
33 self.textlog.finished()
34 35 36 # /builders/$builder/builds/$buildnum/steps/$stepname/logs/$logname
37 -class TextLog(Resource):
38 # a new instance of this Resource is created for each client who views 39 # it, so we can afford to track the request in the Resource. 40 implements(IHTMLLog) 41 42 asText = False 43 subscribed = False 44
45 - def __init__(self, original):
46 Resource.__init__(self) 47 self.original = original
48
49 - def getChild(self, path, req):
50 if path == "text": 51 self.asText = True 52 return self 53 return HtmlResource.getChild(self, path, req)
54
55 - def content(self, entries):
56 html_entries = [] 57 text_data = '' 58 for type, entry in entries: 59 if type >= len(builder.ChunkTypes) or type < 0: 60 # non-std channel, don't display 61 continue 62 63 is_header = type == builder.HEADER 64 65 if not self.asText: 66 # jinja only works with unicode, or pure ascii, so assume utf-8 in logs 67 if not isinstance(entry, unicode): 68 entry = unicode(entry, 'utf-8', 'replace') 69 html_entries.append(dict(type = builder.ChunkTypes[type], 70 text = entry, 71 is_header = is_header)) 72 elif not is_header: 73 text_data += entry 74 75 if self.asText: 76 return text_data 77 else: 78 return self.template.module.chunks(html_entries)
79
80 - def render_HEAD(self, req):
81 self._setContentType(req) 82 83 # vague approximation, ignores markup 84 req.setHeader("content-length", self.original.length) 85 return ''
86
87 - def render_GET(self, req):
88 self._setContentType(req) 89 self.req = req 90 91 if not self.asText: 92 self.template = req.site.buildbot_service.templates.get_template("logs.html") 93 94 data = self.template.module.page_header( 95 title = "Log File contents", 96 texturl = req.childLink("text"), 97 path_to_root = path_to_root(req)) 98 data = data.encode('utf-8') 99 req.write(data) 100 101 self.original.subscribeConsumer(ChunkConsumer(req, self)) 102 return server.NOT_DONE_YET
103
104 - def _setContentType(self, req):
105 if self.asText: 106 req.setHeader("content-type", "text/plain; charset=utf-8") 107 else: 108 req.setHeader("content-type", "text/html; charset=utf-8")
109
110 - def finished(self):
111 if not self.req: 112 return 113 try: 114 if not self.asText: 115 data = self.template.module.page_footer() 116 data = data.encode('utf-8') 117 self.req.write(data) 118 self.req.finish() 119 except pb.DeadReferenceError: 120 pass 121 # break the cycle, the Request's .notifications list includes the 122 # Deferred (from req.notifyFinish) that's pointing at us. 123 self.req = None 124 125 # release template 126 self.template = None
127 128 components.registerAdapter(TextLog, interfaces.IStatusLog, IHTMLLog) 129 130
131 -class HTMLLog(Resource):
132 implements(IHTMLLog) 133
134 - def __init__(self, original):
135 Resource.__init__(self) 136 self.original = original
137
138 - def render(self, request):
139 request.setHeader("content-type", "text/html") 140 return self.original.html
141 142 components.registerAdapter(HTMLLog, builder.HTMLLogFile, IHTMLLog) 143 144
145 -class LogsResource(HtmlResource):
146 addSlash = True 147
148 - def __init__(self, step_status):
151
152 - def getChild(self, path, req):
153 for log in self.step_status.getLogs(): 154 if path == log.getName(): 155 if log.hasContents(): 156 return IHTMLLog(interfaces.IStatusLog(log)) 157 return NoResource("Empty Log '%s'" % path) 158 return HtmlResource.getChild(self, path, req)
159