From 524bdae950f36d540b18ee5ad7910fadf45e30d1 Mon Sep 17 00:00:00 2001
From: Mike Bayer <mike_mp@zzzcomputing.com>
Date: Fri, 5 Mar 2010 01:37:41 +0000
Subject: [PATCH] - RichTraceback(), html_error_template().render(),  
 text_error_template().render() now accept "error"   and "traceback" as
 optional arguments, and   these are now actually used.  [ticket:122]

---
 CHANGES                 | 10 ++++++++++
 mako/exceptions.py      | 29 ++++++++++++++++++-----------
 mako/runtime.py         |  5 ++++-
 test/test_exceptions.py | 28 ++++++++++++++++++++++++----
 4 files changed, 56 insertions(+), 16 deletions(-)

diff --git a/CHANGES b/CHANGES
index d3ed5ea..badefd8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -15,6 +15,16 @@
   is regenerated from parsed Python source.
   This fixes usage of unicode in 
   <%namespace:defname> tags.  [ticket:99]
+
+- RichTraceback(), html_error_template().render(),
+  text_error_template().render() now accept "error"
+  and "traceback" as optional arguments, and 
+  these are now actually used.  [ticket:122]
+  
+- The exception output generated when 
+  format_exceptions=True will now be as a Python
+  unicode if it occurred during render_unicode(),
+  or an encoded string if during render().
   
 0.2.6
 
diff --git a/mako/exceptions.py b/mako/exceptions.py
index daba4fd..d59d868 100644
--- a/mako/exceptions.py
+++ b/mako/exceptions.py
@@ -73,14 +73,18 @@ class RichTraceback(object):
     
     """
     def __init__(self, error=None, traceback=None):
-        (self.source, self.lineno) = ("", 0)
+        self.source, self.lineno = "", 0
 
         if error is None or traceback is None:
-            t, value, traceback = sys.exc_info()
-            self.error = value or t
-        else:
-            self.error = error
+            t, value, tback = sys.exc_info()
+        
+        if error is None:
+            error = value or t
+            
+        if traceback is None:
+            traceback = tback
             
+        self.error = error
         self.records = self._init(traceback)
             
         if isinstance(self.error, (CompileException, SyntaxException)):
@@ -88,11 +92,10 @@ class RichTraceback(object):
             self.source = self.error.source
             self.lineno = self.error.lineno
             self._has_source = True
-        self.reverse_records = [r for r in self.records]
-        self.reverse_records.reverse()
-        self.init_message()
+            
+        self._init_message()
 
-    def init_message(self):
+    def _init_message(self):
         """Find a unicode representation of self.error"""
         try:
             self.message = unicode(self.error)
@@ -118,13 +121,17 @@ class RichTraceback(object):
         """return a list of 4-tuple traceback records (i.e. normal python format)
             with template-corresponding lines remapped to the originating template
         """
-        return self._get_reformatted_records(self.records)
+        return list(self._get_reformatted_records(self.records))
     
+    @property
+    def reverse_records(self):
+        return reversed(self.records)
+        
     @property
     def reverse_traceback(self):
         """return the same data as traceback, except in reverse order
         """
-        return self._get_reformatted_records(self.reverse_records)
+        return list(self._get_reformatted_records(self.reverse_records))
 
     def _init(self, trcback):
         """format a traceback from sys.exc_info() into 7-item tuples, containing
diff --git a/mako/runtime.py b/mako/runtime.py
index 95828b4..19d79de 100644
--- a/mako/runtime.py
+++ b/mako/runtime.py
@@ -430,6 +430,9 @@ def _render_error(template, context, error):
         if context._outputting_as_unicode:
             context._buffer_stack[:] = [util.FastEncodingBuffer(unicode=True)]
         else:
-            context._buffer_stack[:] = [util.FastEncodingBuffer(error_template.output_encoding, error_template.encoding_errors)]
+            context._buffer_stack[:] = [util.FastEncodingBuffer(
+                                            error_template.output_encoding,
+                                            error_template.encoding_errors)]
+                                            
         context._with_template = error_template
         error_template.render_context(context, error=error)
diff --git a/test/test_exceptions.py b/test/test_exceptions.py
index 57b3bac..e64afc2 100644
--- a/test/test_exceptions.py
+++ b/test/test_exceptions.py
@@ -86,7 +86,6 @@ ${u'привет'}
                 assert 'RuntimeError: test' in html_error
                 assert "foo = u'&#x65E5;&#x672C;'" in html_error
 
-
     def test_py_unicode_error_html_error_template(self):
         try:
             raise RuntimeError(u'日本')
@@ -106,10 +105,12 @@ ${foobar}
         ${self.body()}
         """)
 
-        assert '<div class="sourceline">${foobar}</div>' in result_lines(l.get_template("foo.html").render_unicode())
+        assert '<div class="sourceline">${foobar}</div>' in \
+                result_lines(l.get_template("foo.html").render_unicode())
     
     def test_utf8_format_exceptions(self):
-        """test that htmlentityreplace formatting is applied to exceptions reported with format_exceptions=True"""
+        """test that htmlentityreplace formatting is applied to 
+           exceptions reported with format_exceptions=True"""
         
         l = TemplateLookup(format_exceptions=True)
         if util.py3k:
@@ -121,6 +122,25 @@ ${foobar}
             assert u'<div class="sourceline">${\'привет\' + foobar}</div>'\
                 in result_lines(l.get_template("foo.html").render().decode('utf-8'))
         else:
-            assert '<div class="highlight">2 ${u\'&#x43F;&#x440;&#x438;&#x432;&#x435;&#x442;\' + foobar}</div>' \
+            assert '<div class="highlight">2 ${u\'&#x43F;&#x440;'\
+                    '&#x438;&#x432;&#x435;&#x442;\' + foobar}</div>' \
                 in result_lines(l.get_template("foo.html").render().decode('utf-8'))
         
+    
+    def test_custom_tback(self):
+        try:
+            raise RuntimeError("error 1")
+            foo('bar')
+        except:
+            t, v, tback = sys.exc_info()
+        
+        try:
+            raise RuntimeError("error 2")
+        except:
+            html_error = exceptions.html_error_template().render(error=t, traceback=tback)
+        
+        # obfuscate the text so that this text
+        # isn't in the 'wrong' exception
+        assert "".join(reversed(")'rab'(oof")) in html_error
+        
+        
\ No newline at end of file
-- 
GitLab