~landscape/zope3/newer-from-ztk

« back to all changes in this revision

Viewing changes to src/twisted/web/util.py

  • Committer: Thomas Hervé
  • Date: 2009-07-08 13:52:04 UTC
  • Revision ID: thomas@canonical.com-20090708135204-df5eesrthifpylf8
Remove twisted copy

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- test-case-name: twisted.web.test.test_web -*-
2
 
 
3
 
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
4
 
# See LICENSE for details.
5
 
 
6
 
 
7
 
from cStringIO import StringIO
8
 
 
9
 
from twisted.python import failure
10
 
 
11
 
import html
12
 
import resource
13
 
 
14
 
 
15
 
import linecache
16
 
import string, re
17
 
import types
18
 
 
19
 
 
20
 
def redirectTo(URL, request):
21
 
    request.redirect(URL)
22
 
    return """
23
 
<html>
24
 
    <head>
25
 
        <meta http-equiv=\"refresh\" content=\"0;URL=%(url)s\">
26
 
    </head>
27
 
    <body bgcolor=\"#FFFFFF\" text=\"#000000\">
28
 
    <a href=\"%(url)s\">click here</a>
29
 
    </body>
30
 
</html>
31
 
""" % {'url': URL}
32
 
 
33
 
class Redirect(resource.Resource):
34
 
 
35
 
    isLeaf = 1
36
 
    
37
 
    def __init__(self, url):
38
 
        resource.Resource.__init__(self)
39
 
        self.url = url
40
 
 
41
 
    def render(self, request):
42
 
        return redirectTo(self.url, request)
43
 
 
44
 
    def getChild(self, name, request):
45
 
        return self
46
 
 
47
 
class ChildRedirector(Redirect):
48
 
    isLeaf = 0
49
 
    def __init__(self, url):
50
 
        # XXX is this enough?
51
 
        if ((url.find('://') == -1)
52
 
            and (not url.startswith('..'))
53
 
            and (not url.startswith('/'))):
54
 
            raise ValueError("It seems you've given me a redirect (%s) that is a child of myself! That's not good, it'll cause an infinite redirect." % url)
55
 
        Redirect.__init__(self, url)
56
 
 
57
 
    def getChild(self, name, request):
58
 
        newUrl = self.url
59
 
        if not newUrl.endswith('/'):
60
 
            newUrl += '/'
61
 
        newUrl += name
62
 
        return ChildRedirector(newUrl)
63
 
 
64
 
 
65
 
from twisted.python import urlpath
66
 
 
67
 
class ParentRedirect(resource.Resource):
68
 
    """
69
 
    I redirect to URLPath.here().
70
 
    """
71
 
    isLeaf = 1
72
 
    def render(self, request):
73
 
        return redirectTo(urlpath.URLPath.fromRequest(request).here(), request)
74
 
 
75
 
    def getChild(self, request):
76
 
        return self
77
 
 
78
 
 
79
 
class DeferredResource(resource.Resource):
80
 
    """
81
 
    I wrap up a Deferred that will eventually result in a Resource
82
 
    object.
83
 
    """
84
 
    isLeaf = 1
85
 
    
86
 
    def __init__(self, d):
87
 
        resource.Resource.__init__(self)
88
 
        self.d = d
89
 
 
90
 
    def getChild(self, name, request):
91
 
        return self
92
 
    
93
 
    def render(self, request):
94
 
        self.d.addCallback(self._cbChild, request).addErrback(
95
 
            self._ebChild,request)
96
 
        from twisted.web.server import NOT_DONE_YET
97
 
        return NOT_DONE_YET
98
 
 
99
 
    def _cbChild(self, child, request):
100
 
        result = resource.getChildForRequest(child, request).render(request)
101
 
        from twisted.web.server import NOT_DONE_YET
102
 
        if result == NOT_DONE_YET:
103
 
            return
104
 
        else:
105
 
            request.write(result)
106
 
            request.finish()
107
 
 
108
 
    def _ebChild(self, reason, request):
109
 
        request.processingFailed(reason)
110
 
        return reason
111
 
 
112
 
 
113
 
stylesheet = """
114
 
<style type="text/css">
115
 
    p.error {
116
 
      color: red;
117
 
      font-family: Verdana, Arial, helvetica, sans-serif;
118
 
      font-weight: bold;
119
 
    }
120
 
 
121
 
    div {
122
 
      font-family: Verdana, Arial, helvetica, sans-serif;
123
 
    }
124
 
 
125
 
    div.stackTrace {
126
 
    }
127
 
 
128
 
    div.frame {
129
 
      padding: 1em;
130
 
      background: white;
131
 
      border-bottom: thin black dashed;
132
 
    }
133
 
 
134
 
    div.firstFrame {
135
 
      padding: 1em;
136
 
      background: white;
137
 
      border-top: thin black dashed;
138
 
      border-bottom: thin black dashed;
139
 
    }
140
 
 
141
 
    div.location {
142
 
    }
143
 
 
144
 
    div.snippet {
145
 
      margin-bottom: 0.5em;
146
 
      margin-left: 1em;
147
 
      background: #FFFFDD;
148
 
    }
149
 
 
150
 
    div.snippetHighlightLine {
151
 
      color: red;
152
 
    }
153
 
 
154
 
    span.code {
155
 
      font-family: "Courier New", courier, monotype;
156
 
    }
157
 
 
158
 
    span.function {
159
 
      font-weight: bold;
160
 
      font-family: "Courier New", courier, monotype;
161
 
    }
162
 
 
163
 
    table.variables {
164
 
      border-collapse: collapse;
165
 
      margin-left: 1em;
166
 
    }
167
 
 
168
 
    td.varName {
169
 
      vertical-align: top;
170
 
      font-weight: bold;
171
 
      padding-left: 0.5em;
172
 
      padding-right: 0.5em;
173
 
    }
174
 
 
175
 
    td.varValue {
176
 
      padding-left: 0.5em;
177
 
      padding-right: 0.5em;
178
 
    }
179
 
 
180
 
    div.variables {
181
 
      margin-bottom: 0.5em;
182
 
    }
183
 
 
184
 
    span.heading {
185
 
      font-weight: bold;
186
 
    }
187
 
 
188
 
    div.dict {
189
 
      background: #cccc99;
190
 
      padding: 2px;
191
 
      float: left;
192
 
    }
193
 
 
194
 
    td.dictKey {
195
 
      background: #ffff99;
196
 
      font-weight: bold;
197
 
    }
198
 
 
199
 
    td.dictValue {
200
 
      background: #ffff99;
201
 
    }
202
 
 
203
 
    div.list {
204
 
      background: #7777cc;
205
 
      padding: 2px;
206
 
      float: left;
207
 
    }
208
 
 
209
 
    div.listItem {
210
 
      background: #9999ff;
211
 
    }
212
 
 
213
 
    div.instance {
214
 
      background: #cc7777;
215
 
      padding: 2px;
216
 
      float: left;
217
 
    }
218
 
 
219
 
    span.instanceName {
220
 
      font-weight: bold;
221
 
      display: block;
222
 
    }
223
 
 
224
 
    span.instanceRepr {
225
 
      background: #ff9999;
226
 
      font-family: "Courier New", courier, monotype;
227
 
    }
228
 
 
229
 
    div.function {
230
 
      background: orange;
231
 
      font-weight: bold;
232
 
      float: left;
233
 
    }
234
 
</style>
235
 
"""
236
 
 
237
 
 
238
 
def htmlrepr(x):
239
 
    return htmlReprTypes.get(type(x), htmlUnknown)(x)
240
 
 
241
 
def saferepr(x):
242
 
    try:
243
 
        rx = repr(x)
244
 
    except:
245
 
        rx = "<repr failed! %s instance at %s>" % (x.__class__, id(x))
246
 
    return rx
247
 
 
248
 
def htmlUnknown(x):
249
 
    return '<code>'+html.escape(saferepr(x))+'</code>'
250
 
 
251
 
def htmlDict(d):
252
 
    io = StringIO()
253
 
    w = io.write
254
 
    w('<div class="dict"><span class="heading">Dictionary instance @ %s</span>' % hex(id(d)))
255
 
    w('<table class="dict">')
256
 
    for k, v in d.items():
257
 
 
258
 
        if k == '__builtins__':
259
 
            v = 'builtin dictionary'
260
 
        w('<tr><td class="dictKey">%s</td><td class="dictValue">%s</td></tr>' % (htmlrepr(k), htmlrepr(v)))
261
 
    w('</table></div>')
262
 
    return io.getvalue()
263
 
 
264
 
def htmlList(l):
265
 
    io = StringIO()
266
 
    w = io.write
267
 
    w('<div class="list"><span class="heading">List instance @ %s</span>' % hex(id(l)))
268
 
    for i in l:
269
 
        w('<div class="listItem">%s</div>' % htmlrepr(i))
270
 
    w('</div>')
271
 
    return io.getvalue()
272
 
 
273
 
def htmlInst(i):
274
 
    if hasattr(i, "__html__"):
275
 
        s = i.__html__()
276
 
    else:
277
 
        s = html.escape(saferepr(i))
278
 
    return '''<div class="instance"><span class="instanceName">%s instance @ %s</span>
279
 
              <span class="instanceRepr">%s</span></div>
280
 
              ''' % (i.__class__, hex(id(i)), s)
281
 
 
282
 
def htmlString(s):
283
 
    return html.escape(saferepr(s))
284
 
 
285
 
def htmlFunc(f):
286
 
    return ('<div class="function">' +
287
 
            html.escape("function %s in file %s at line %s" %
288
 
                        (f.__name__, f.func_code.co_filename,
289
 
                         f.func_code.co_firstlineno))+
290
 
            '</div>')
291
 
 
292
 
htmlReprTypes = {types.DictType: htmlDict,
293
 
                 types.ListType: htmlList,
294
 
                 types.InstanceType: htmlInst,
295
 
                 types.StringType: htmlString,
296
 
                 types.FunctionType: htmlFunc}
297
 
 
298
 
 
299
 
 
300
 
def htmlIndent(snippetLine):
301
 
    ret = string.replace(string.replace(html.escape(string.rstrip(snippetLine)),
302
 
                                  '  ', '&nbsp;'),
303
 
                   '\t', '&nbsp; &nbsp; &nbsp; &nbsp; ')
304
 
    return ret
305
 
 
306
 
def formatFailure(myFailure):
307
 
 
308
 
    exceptionHTML = """
309
 
<p class="error">%s: %s</p>
310
 
"""
311
 
 
312
 
    frameHTML = """
313
 
<div class="location">%s, line %s in <span class="function">%s</span></div>
314
 
"""
315
 
 
316
 
    snippetLineHTML = """
317
 
<div class="snippetLine"><span class="lineno">%s</span><span class="code">%s</span></div>
318
 
"""
319
 
 
320
 
    snippetHighlightLineHTML = """
321
 
<div class="snippetHighlightLine"><span class="lineno">%s</span><span class="code">%s</span></div>
322
 
"""
323
 
 
324
 
    variableHTML = """
325
 
<tr class="varRow"><td class="varName">%s</td><td class="varValue">%s</td></tr>
326
 
"""
327
 
    
328
 
    if not isinstance(myFailure, failure.Failure):
329
 
        return html.PRE(str(myFailure))
330
 
    io = StringIO()
331
 
    w = io.write
332
 
    w(stylesheet)
333
 
    w('<a href="#tbend">')
334
 
    w(exceptionHTML % (html.escape(str(myFailure.type)),
335
 
                       html.escape(str(myFailure.value))))
336
 
    w('</a>')
337
 
    w('<div class="stackTrace">')
338
 
    first = 1
339
 
    for method, filename, lineno, localVars, globalVars in myFailure.frames:
340
 
        if filename == '<string>':
341
 
            continue
342
 
        if first:
343
 
            w('<div class="firstFrame">')
344
 
            first = 0
345
 
        else:
346
 
            w('<div class="frame">')
347
 
        w(frameHTML % (filename, lineno, method))
348
 
 
349
 
        w('<div class="snippet">')
350
 
        textSnippet = ''
351
 
        for snipLineNo in range(lineno-2, lineno+2):
352
 
            snipLine = linecache.getline(filename, snipLineNo)
353
 
            textSnippet += snipLine
354
 
            snipLine = htmlIndent(snipLine)
355
 
            if snipLineNo == lineno:
356
 
                w(snippetHighlightLineHTML % (snipLineNo, snipLine))
357
 
            else:
358
 
                w(snippetLineHTML % (snipLineNo, snipLine))
359
 
        w('</div>')
360
 
 
361
 
        # Instance variables
362
 
        for name, var in localVars:
363
 
            if name == 'self' and hasattr(var, '__dict__'):
364
 
                usedVars = [ (key, value) for (key, value) in var.__dict__.items()
365
 
                             if re.search(r'\W'+'self.'+key+r'\W', textSnippet) ]
366
 
                if usedVars:
367
 
                    w('<div class="variables"><b>Self</b>')
368
 
                    w('<table class="variables">')
369
 
                    for key, value in usedVars:
370
 
                        w(variableHTML % (key, htmlrepr(value)))
371
 
                    w('</table></div>')
372
 
                break
373
 
 
374
 
        # Local and global vars
375
 
        for nm, varList in ('Locals', localVars), ('Globals', globalVars):
376
 
            usedVars = [ (name, var) for (name, var) in varList
377
 
                         if re.search(r'\W'+name+r'\W', textSnippet) ]
378
 
            if usedVars:
379
 
                w('<div class="variables"><b>%s</b><table class="variables">' % nm)
380
 
                for name, var in usedVars:
381
 
                    w(variableHTML % (name, htmlrepr(var)))
382
 
                w('</table></div>')
383
 
            
384
 
        w('</div>') # frame
385
 
    w('</div>') # stacktrace
386
 
    w('<a name="tbend"> </a>')
387
 
    w(exceptionHTML % (html.escape(str(myFailure.type)),
388
 
                       html.escape(str(myFailure.value))))
389
 
 
390
 
    return io.getvalue()