1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 from zope.interface import implements
18 from twisted.python import components
19 from twisted.spread import pb
20 from twisted.web import server
21 from twisted.web.resource import Resource, NoResource
22
23 from buildbot import interfaces
24 from buildbot.status import logfile
25 from buildbot.status.web.base import IHTMLLog, HtmlResource, path_to_root
26
28 implements(interfaces.IStatusLogConsumer)
29
31 self.original = original
32 self.textlog = textlog
34 self.producer = producer
35 self.original.registerProducer(producer, streaming)
39 formatted = self.textlog.content([chunk])
40 try:
41 if isinstance(formatted, unicode):
42 formatted = formatted.encode('utf-8')
43 self.original.write(formatted)
44 except pb.DeadReferenceError:
45 self.producing.stopProducing()
48
49
50
51 -class TextLog(Resource):
52
53
54 implements(IHTMLLog)
55
56 asText = False
57 subscribed = False
58
59 - def __init__(self, original):
60 Resource.__init__(self)
61 self.original = original
62
63 - def getChild(self, path, req):
64 if path == "text":
65 self.asText = True
66 return self
67 return Resource.getChild(self, path, req)
68
69 - def content(self, entries):
70 html_entries = []
71 text_data = ''
72 for type, entry in entries:
73 if type >= len(logfile.ChunkTypes) or type < 0:
74
75 continue
76
77 is_header = type == logfile.HEADER
78
79 if not self.asText:
80
81 if not isinstance(entry, unicode):
82 entry = unicode(entry, 'utf-8', 'replace')
83 html_entries.append(dict(type = logfile.ChunkTypes[type],
84 text = entry,
85 is_header = is_header))
86 elif not is_header:
87 text_data += entry
88
89 if self.asText:
90 return text_data
91 else:
92 return self.template.module.chunks(html_entries)
93
94 - def render_HEAD(self, req):
95 self._setContentType(req)
96
97
98 req.setHeader("content-length", self.original.length)
99 return ''
100
101 - def render_GET(self, req):
102 self._setContentType(req)
103 self.req = req
104
105 if (self.original.isFinished()):
106 req.setHeader("Cache-Control", "max-age=604800")
107 else:
108 req.setHeader("Cache-Control", "no-cache")
109
110 if not self.asText:
111 self.template = req.site.buildbot_service.templates.get_template("logs.html")
112
113 data = self.template.module.page_header(
114 pageTitle = "Log File contents",
115 texturl = req.childLink("text"),
116 path_to_root = path_to_root(req))
117 data = data.encode('utf-8')
118 req.write(data)
119
120 self.original.subscribeConsumer(ChunkConsumer(req, self))
121 return server.NOT_DONE_YET
122
123 - def _setContentType(self, req):
124 if self.asText:
125 req.setHeader("content-type", "text/plain; charset=utf-8")
126 else:
127 req.setHeader("content-type", "text/html; charset=utf-8")
128
129 - def finished(self):
130 if not self.req:
131 return
132 try:
133 if not self.asText:
134 data = self.template.module.page_footer()
135 data = data.encode('utf-8')
136 self.req.write(data)
137 self.req.finish()
138 except pb.DeadReferenceError:
139 pass
140
141
142 self.req = None
143
144
145 self.template = None
146
147 components.registerAdapter(TextLog, interfaces.IStatusLog, IHTMLLog)
148
149
151 implements(IHTMLLog)
152
154 Resource.__init__(self)
155 self.original = original
156
158 request.setHeader("content-type", "text/html")
159 return self.original.html
160
161 components.registerAdapter(HTMLLog, logfile.HTMLLogFile, IHTMLLog)
162
163
178