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()

_______________________________________________
Twisted-web mailing list
[email protected]
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web

Reply via email to