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
14 implements(interfaces.IStatusLogConsumer)
15
17 self.original = original
18 self.textlog = textlog
20 self.producer = producer
21 self.original.registerProducer(producer, streaming)
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()
34
35
36
37 -class TextLog(Resource):
38
39
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
61 continue
62
63 is_header = type == builder.HEADER
64
65 if not self.asText:
66
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
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
122
123 self.req = None
124
125
126 self.template = None
127
128 components.registerAdapter(TextLog, interfaces.IStatusLog, IHTMLLog)
129
130
132 implements(IHTMLLog)
133
135 Resource.__init__(self)
136 self.original = original
137
139 request.setHeader("content-type", "text/html")
140 return self.original.html
141
142 components.registerAdapter(HTMLLog, builder.HTMLLogFile, IHTMLLog)
143
144
159