diff -r 6346f53c85f1 -r 0aebb1c0f849 utils.py --- a/utils.py Wed Nov 19 11:57:55 2014 +0100 +++ b/utils.py Wed Nov 19 12:13:32 2014 +0100 @@ -206,12 +206,23 @@ specifed in the constructor """ + def __init__(self, tracewrites=False, *args, **kwargs): + self.tracewrites = tracewrites + super(UStringIO, self).__init__(*args, **kwargs) + def __nonzero__(self): return True def write(self, value): assert isinstance(value, unicode), u"unicode required not %s : %s"\ % (type(value).__name__, repr(value)) + if self.tracewrites: + from traceback import format_stack + stack = format_stack(None)[:-1] + escaped_stack = xml_escape(json_dumps(u'\n'.join(stack))) + escaped_html = xml_escape(value).replace('\n', '
\n') + tpl = u'%s' + value = tpl % (escaped_stack, escaped_html) self.append(value) def getvalue(self): @@ -234,8 +245,8 @@ script_opening = u'' - def __init__(self, req): - super(HTMLHead, self).__init__() + def __init__(self, req, *args, **kwargs): + super(HTMLHead, self).__init__(*args, **kwargs) self.jsvars = [] self.jsfiles = [] self.cssfiles = [] @@ -399,10 +410,15 @@ w(self.script_opening) w(u'\n\n'.join(self.post_inlined_scripts)) w(self.script_closing) - header = super(HTMLHead, self).getvalue() - if skiphead: - return header - return u'\n%s\n' % header + # at the start of this function, the parent UStringIO may already have + # data in it, so we can't w(u'\n') at the top. Instead, we create + # a temporary UStringIO to get the same debugging output formatting + # if debugging is enabled. + headtag = UStringIO(tracewrites=self.tracewrites) + if not skiphead: + headtag.write(u'\n') + w(u'\n') + return headtag.getvalue() + super(HTMLHead, self).getvalue() class HTMLStream(object): @@ -416,10 +432,11 @@ """ def __init__(self, req): + self.tracehtml = req.tracehtml # stream for self.head = req.html_headers # main stream - self.body = UStringIO() + self.body = UStringIO(tracewrites=req.tracehtml) # this method will be assigned to self.w in views self.write = self.body.write self.doctype = u'' @@ -457,6 +474,26 @@ def getvalue(self): """writes HTML headers, closes tag and writes HTML body""" + if self.tracehtml: + css = u'\n'.join((u'span {', + u' font-family: monospace;', + u' word-break: break-all;', + u' word-wrap: break-word;', + u'}', + u'span:hover {', + u' color: red;', + u' text-decoration: underline;', + u'}')) + style = u'\n' % css + return (u'\n' + + u'\n\n%s\n\n' % style + + u'\n' + + u'' + xml_escape(self.doctype) + u'
' + + u'' + xml_escape(self.htmltag) + u'
' + + self.head.getvalue() + + self.body.getvalue() + + u'' + xml_escape(u'') + u'' + + u'\n') return u'%s\n%s\n%s\n%s\n' % (self.doctype, self.htmltag, self.head.getvalue(),