From 65f8a3b715e8519ca5ca5d835240fe45aa4b96fa Mon Sep 17 00:00:00 2001 From: Martin von Gagern Date: Tue, 2 Jul 2019 17:10:23 -0400 Subject: Include URI in traceback if filename is unknown Using URIs as entrered will make the stack trace arguably more readable than using the module name which is the URI with non-word characters replaced by underscores. This change also fixes a mistake where a mods cache hit would not update template_filename, causing a stale filename to be displayed if the stack trace alternates between different templates. There now is a test case for this. Closes: #298 Pull-request: https://github.com/sqlalchemy/mako/pull/298 Pull-request-sha: ea35208d504932561711cdb574ec1f7def1e7060 Change-Id: Ieb606f6b6b7f4602d4d56694dd0bccf6dc287d20 --- doc/build/unreleased/uri_traceback.rst | 9 ++++++ mako/exceptions.py | 10 +++++-- mako/template.py | 9 ++++-- test/test_exceptions.py | 50 ++++++++++++++++++++++++++++++---- 4 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 doc/build/unreleased/uri_traceback.rst diff --git a/doc/build/unreleased/uri_traceback.rst b/doc/build/unreleased/uri_traceback.rst new file mode 100644 index 0000000..43787b9 --- /dev/null +++ b/doc/build/unreleased/uri_traceback.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, exceptions + + Fixed issue where the correct file URI would not be shown in the + template-formatted exception traceback if the template filename were not + known. Additionally fixes an issue where stale filenames would be + displayed if a stack trace alternated between different templates. Pull + request courtesy Martin von Gagern. + diff --git a/mako/exceptions.py b/mako/exceptions.py index 283391a..b6388b1 100644 --- a/mako/exceptions.py +++ b/mako/exceptions.py @@ -159,13 +159,17 @@ class RichTraceback(object): if not line: line = "" try: - (line_map, template_lines) = mods[filename] + (line_map, template_lines, template_filename) = mods[filename] except KeyError: try: info = mako.template._get_module_info(filename) module_source = info.code template_source = info.source - template_filename = info.template_filename or filename + template_filename = ( + info.template_filename + or info.template_uri + or filename + ) except KeyError: # A normal .py file (not a Template) if not compat.py3k: @@ -204,7 +208,7 @@ class RichTraceback(object): template_lines = [ line_ for line_ in template_source.split("\n") ] - mods[filename] = (line_map, template_lines) + mods[filename] = (line_map, template_lines, template_filename) template_ln = line_map[lineno - 1] diff --git a/mako/template.py b/mako/template.py index 2cd1ef4..8e87d50 100644 --- a/mako/template.py +++ b/mako/template.py @@ -330,7 +330,7 @@ class Template(object): (code, module) = _compile_text(self, text, filename) self._code = code self._source = text - ModuleInfo(module, None, self, filename, code, text) + ModuleInfo(module, None, self, filename, code, text, uri) elif filename is not None: # if template filename and a module directory, load # a filesystem-based module file, generating if needed @@ -421,7 +421,7 @@ class Template(object): ) module = compat.load_module(self.module_id, path) del sys.modules[self.module_id] - ModuleInfo(module, path, self, filename, None, None) + ModuleInfo(module, path, self, filename, None, None, None) else: # template filename and no module directory, compile code # in memory @@ -429,7 +429,7 @@ class Template(object): code, module = _compile_text(self, data, filename) self._source = None self._code = code - ModuleInfo(module, None, self, filename, code, None) + ModuleInfo(module, None, self, filename, code, None, None) return module @property @@ -584,6 +584,7 @@ class ModuleTemplate(Template): template_filename, module_source, template_source, + module._template_uri, ) self.callable_ = self.module.render_body @@ -641,12 +642,14 @@ class ModuleInfo(object): template_filename, module_source, template_source, + template_uri, ): self.module = module self.module_filename = module_filename self.template_filename = template_filename self.module_source = module_source self.template_source = template_source + self.template_uri = template_uri self._modules[module.__name__] = template._mmarker = self if module_filename: self._modules[module_filename] = self diff --git a/test/test_exceptions.py b/test/test_exceptions.py index 46fbcdd..2ec46cf 100644 --- a/test/test_exceptions.py +++ b/test/test_exceptions.py @@ -398,10 +398,9 @@ raise RuntimeError(msg) # This is the line. t = l.get_template("foo.html") try: t.render() - assert False except: text_error = exceptions.text_error_template().render_unicode() - assert 'File "foo_html", line 4, in render_body' in text_error + assert 'File "foo.html", line 4, in render_body' in text_error assert "raise RuntimeError(msg) # This is the line." in text_error else: assert False @@ -422,12 +421,51 @@ ${foo()} t = l.get_template("foo.html") try: t.render() - assert False except: text_error = exceptions.text_error_template().render_unicode() - sys.stderr.write(text_error) - assert 'File "foo_html", line 7, in render_body' in text_error - assert 'File "foo_html", line 5, in foo' in text_error + assert 'File "foo.html", line 7, in render_body' in text_error + assert 'File "foo.html", line 5, in foo' in text_error assert "raise RuntimeError(msg) # This is the line." in text_error else: assert False + + def test_alternating_file_names(self): + l = TemplateLookup() + l.put_string( + "base.html", + """ +<%! +def broken(): + raise RuntimeError("Something went wrong.") +%> body starts here +<%block name="foo"> + ${broken()} + + """, + ) + l.put_string( + "foo.html", + """ +<%inherit file="base.html"/> +<%block name="foo"> + ${parent.foo()} + + """, + ) + t = l.get_template("foo.html") + try: + t.render() + except: + text_error = exceptions.text_error_template().render_unicode() + assert """ + File "base.html", line 5, in render_body + %> body starts here + File "foo.html", line 4, in render_foo + ${parent.foo()} + File "base.html", line 7, in render_foo + ${broken()} + File "base.html", line 4, in broken + raise RuntimeError("Something went wrong.") +""" in text_error + else: + assert False -- cgit v1.2.3