[Twisted-web] formatFailure recursion problems
Phil Christensen
phil at bubblehouse.org
Wed Mar 26 14:30:39 EDT 2008
I've been using formatFailure recently to provide pretty tracebacks in
my webapp, and I'm loving it, but I've run into a scenario where I've
got a recursive data structure that occasionally pops up in
tracebacks, and causes formatFailure all kinds of problems.
Now, I can't really do much about the recursion itself, because it
appears to be an unfortunate side effect of embedding Trac into a WSGI
app I've written (the app just passes its environ variable to trac,
acting as pseudo-transparent middleware).
So, the real question is, is there anything that can be done to make
formatFailure deal with recursion more gracefully? I'm currently using
a extremely quick-and-dirty hack that just caches the id of each
non-'primitive' object, and returns '==RECURSION==' when it encounters
the id a second time.
I guess what would be ideal is if it were possible could set some kind
of depth limit for the htmlrepr() stuff, since most of the time I have
no need to see that "deeply" into a local or global variable.
I'm glad to work on the patch myself, but I was wondering if anyone
has any suggestions as to how this should work. The current patch I'm
using is attached below, but it's pretty overzealous about preventing
recursion; if you output the object once anywhere in the entire
traceback, it will never be output again, even in a non-recursive
scenario.
Anyways, any input would be appreciated...
-phil
Index: twisted/web/util.py
===================================================================
--- twisted/web/util.py (revision 23090)
+++ twisted/web/util.py (working copy)
@@ -234,8 +234,13 @@
</style>
"""
-
+repr_cache = None
def htmlrepr(x):
+ if(repr_cache is not None and type(x) not in (str, int, long,
float, unicode)):
+ if(id(x) in repr_cache):
+ return '==RECURSION=='
+ else:
+ repr_cache[id(x)] = 1
return htmlReprTypes.get(type(x), htmlUnknown)(x)
def saferepr(x):
@@ -304,7 +309,6 @@
return ret
def formatFailure(myFailure):
-
exceptionHTML = """
<p class="error">%s: %s</p>
"""
@@ -325,6 +329,9 @@
<tr class="varRow"><td class="varName">%s</td><td class="varValue">
%s</td></tr>
"""
+ global repr_cache
+ repr_cache = {}
+
if not isinstance(myFailure, failure.Failure):
return html.PRE(str(myFailure))
io = StringIO()
@@ -387,4 +394,5 @@
w(exceptionHTML % (html.escape(str(myFailure.type)),
html.escape(str(myFailure.value))))
+ repr_cache = None
return io.getvalue()
More information about the Twisted-web
mailing list