Use utf-8 encoding for traceback source with no encoding in py3k

Added a default encoding of "utf-8" when the :class:`.RichTraceback`
object retrieves Python source lines from a Python traceback; as these
are bytes in Python 3 they need to be decoded so that they can be
formatted in the template.

Fixes: #293
Change-Id: I41a5c09422d6500c7cab2423ed14ac951a64e2f4
diff --git a/doc/build/changelog.rst b/doc/build/changelog.rst
index 653b241..484dc66 100644
--- a/doc/build/changelog.rst
+++ b/doc/build/changelog.rst
@@ -9,6 +9,15 @@
     :version: 1.0.10
     :include_notes_from: unreleased
 
+    .. change::
+        :tags: bug, py3k
+        :tickets: 293
+
+     Added a default encoding of "utf-8" when the :class:`.RichTraceback`
+     object retrieves Python source lines from a Python traceback; as these
+     are bytes in Python 3 they need to be decoded so that they can be
+     formatted in the template.
+
 .. changelog::
     :version: 1.0.9
     :released: Mon Apr 15 2019
diff --git a/mako/exceptions.py b/mako/exceptions.py
index cb6fb3f..e2d78bd 100644
--- a/mako/exceptions.py
+++ b/mako/exceptions.py
@@ -214,6 +214,8 @@
                         # A normal .py file (not a Template)
                         fp = open(new_trcback[-1][0], 'rb')
                         encoding = util.parse_encoding(fp)
+                        if compat.py3k and not encoding:
+                            encoding = 'utf-8'
                         fp.seek(0)
                         self.source = fp.read()
                         fp.close()
diff --git a/test/foo/mod_no_encoding.py b/test/foo/mod_no_encoding.py
new file mode 100644
index 0000000..2ba6746
--- /dev/null
+++ b/test/foo/mod_no_encoding.py
@@ -0,0 +1,8 @@
+
+from mako.lookup import TemplateLookup
+from mako.exceptions import MakoException, html_error_template
+
+template_lookup = TemplateLookup()
+def run():
+    tpl = template_lookup.get_template('not_found.html')
+
diff --git a/test/test_exceptions.py b/test/test_exceptions.py
index bcaae3b..242577f 100644
--- a/test/test_exceptions.py
+++ b/test/test_exceptions.py
@@ -243,6 +243,15 @@
                    'т' + foobar}' in \
                 result_lines(l.get_template("foo.html").render().decode('utf-8'))
 
+    def test_mod_no_encoding(self):
+
+        mod = __import__("test.foo.mod_no_encoding").foo.mod_no_encoding
+        try:
+           mod.run()
+        except:
+            t, v, tback = sys.exc_info()
+            html_error = exceptions.html_error_template().\
+                        render_unicode(error=v, traceback=tback)
 
     def test_custom_tback(self):
         try: