1   
  2  from zope.interface import implements 
  3  from twisted.python import components 
  4  from twisted.spread import pb 
  5  from twisted.web import html, 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 
 12   
 13   
 14  textlog_stylesheet = """ 
 15  <style type="text/css"> 
 16   div.data { 
 17    font-family: "Courier New", courier, monotype; 
 18   } 
 19   span.stdout { 
 20    font-family: "Courier New", courier, monotype; 
 21   } 
 22   span.stderr { 
 23    font-family: "Courier New", courier, monotype; 
 24    color: red; 
 25   } 
 26   span.header { 
 27    font-family: "Courier New", courier, monotype; 
 28    color: blue; 
 29   } 
 30  </style> 
 31  """ 
 32   
 34      implements(interfaces.IStatusLogConsumer) 
 35   
 37          self.original = original 
 38          self.textlog = textlog 
  40          self.producer = producer 
 41          self.original.registerProducer(producer, streaming) 
  45          formatted = self.textlog.content([chunk]) 
 46          try: 
 47              if isinstance(formatted, unicode): 
 48                  formatted = formatted.encode('utf-8') 
 49              self.original.write(formatted) 
 50          except pb.DeadReferenceError: 
 51              self.producing.stopProducing() 
   54   
 55   
 56   
 57 -class TextLog(Resource): 
  58       
 59       
 60      implements(IHTMLLog) 
 61   
 62      asText = False 
 63      subscribed = False 
 64   
 65 -    def __init__(self, original): 
  66          Resource.__init__(self) 
 67          self.original = original 
  68   
 69 -    def getChild(self, path, req): 
  70          if path == "text": 
 71              self.asText = True 
 72              return self 
 73          return HtmlResource.getChild(self, path, req) 
  74   
 76          title = "Log File contents" 
 77          data = "<html>\n<head><title>" + title + "</title>\n" 
 78          data += textlog_stylesheet 
 79          data += "</head>\n" 
 80          data += "<body vlink=\"#800080\">\n" 
 81          texturl = request.childLink("text") 
 82          data += '<a href="%s">(view as text)</a><br />\n' % texturl 
 83          data += "<pre>\n" 
 84          return data 
  85   
 86 -    def content(self, entries): 
  87          spanfmt = '<span class="%s">%s</span>' 
 88          data = "" 
 89          for type, entry in entries: 
 90              if type >= len(builder.ChunkTypes) or type < 0: 
 91                   
 92                  continue 
 93              if self.asText: 
 94                  if type != builder.HEADER: 
 95                      data += entry 
 96              else: 
 97                  data += spanfmt % (builder.ChunkTypes[type], 
 98                                     html.escape(entry)) 
 99          return data 
 100   
102          data = "</pre>\n" 
103          data += "</body></html>\n" 
104          return data 
 105   
106 -    def render_HEAD(self, request): 
 107          if self.asText: 
108              request.setHeader("content-type", "text/plain") 
109          else: 
110              request.setHeader("content-type", "text/html") 
111   
112           
113          request.setHeader("content-length", self.original.length) 
114          return '' 
 115   
116 -    def render_GET(self, req): 
 117          self.req = req 
118   
119          if self.asText: 
120              req.setHeader("content-type", "text/plain") 
121          else: 
122              req.setHeader("content-type", "text/html") 
123   
124          if not self.asText: 
125              req.write(self.htmlHeader(req)) 
126   
127          self.original.subscribeConsumer(ChunkConsumer(req, self)) 
128          return server.NOT_DONE_YET 
 129   
130 -    def finished(self): 
 131          if not self.req: 
132              return 
133          try: 
134              if not self.asText: 
135                  self.req.write(self.htmlFooter()) 
136              self.req.finish() 
137          except pb.DeadReferenceError: 
138              pass 
139           
140           
141          self.req = None 
  142   
143  components.registerAdapter(TextLog, interfaces.IStatusLog, IHTMLLog) 
144   
145   
147      implements(IHTMLLog) 
148   
150          Resource.__init__(self) 
151          self.original = original 
 152   
154          request.setHeader("content-type", "text/html") 
155          return self.original.html 
  156   
157  components.registerAdapter(HTMLLog, builder.HTMLLogFile, IHTMLLog) 
158   
159   
174