1import sys 2 3from mako import exceptions 4from mako.lookup import TemplateLookup 5from mako.template import Template 6from mako.testing.exclusions import requires_no_pygments_exceptions 7from mako.testing.exclusions import requires_pygments_14 8from mako.testing.fixtures import TemplateTest 9from mako.testing.helpers import result_lines 10 11 12class ExceptionsTest(TemplateTest): 13 def test_html_error_template(self): 14 """test the html_error_template""" 15 code = """ 16% i = 0 17""" 18 try: 19 template = Template(code) 20 template.render_unicode() 21 assert False 22 except exceptions.CompileException: 23 html_error = exceptions.html_error_template().render_unicode() 24 assert ( 25 "CompileException: Fragment 'i = 0' is not " 26 "a partial control statement at line: 2 char: 1" 27 ) in html_error 28 assert "<style>" in html_error 29 html_error_stripped = html_error.strip() 30 assert html_error_stripped.startswith("<html>") 31 assert html_error_stripped.endswith("</html>") 32 33 not_full = exceptions.html_error_template().render_unicode( 34 full=False 35 ) 36 assert "<html>" not in not_full 37 assert "<style>" in not_full 38 39 no_css = exceptions.html_error_template().render_unicode(css=False) 40 assert "<style>" not in no_css 41 else: 42 assert False, ( 43 "This function should trigger a CompileException, " 44 "but didn't" 45 ) 46 47 def test_text_error_template(self): 48 code = """ 49% i = 0 50""" 51 try: 52 template = Template(code) 53 template.render_unicode() 54 assert False 55 except exceptions.CompileException: 56 text_error = exceptions.text_error_template().render_unicode() 57 assert "Traceback (most recent call last):" in text_error 58 assert ( 59 "CompileException: Fragment 'i = 0' is not a partial " 60 "control statement" 61 ) in text_error 62 63 @requires_pygments_14 64 def test_utf8_html_error_template_pygments(self): 65 """test the html_error_template with a Template containing UTF-8 66 chars""" 67 68 code = """# -*- coding: utf-8 -*- 69% if 2 == 2: /an error 70${'привет'} 71% endif 72""" 73 try: 74 template = Template(code) 75 template.render_unicode() 76 except exceptions.CompileException: 77 html_error = exceptions.html_error_template().render() 78 assert ( 79 "CompileException: Fragment 'if 2 == 2: /an " 80 "error' is not a partial control statement " 81 "at line: 2 char: 1" 82 ).encode( 83 sys.getdefaultencoding(), "htmlentityreplace" 84 ) in html_error 85 86 assert ( 87 "".encode(sys.getdefaultencoding(), "htmlentityreplace") 88 in html_error 89 ) 90 else: 91 assert False, ( 92 "This function should trigger a CompileException, " 93 "but didn't" 94 ) 95 96 @requires_no_pygments_exceptions 97 def test_utf8_html_error_template_no_pygments(self): 98 """test the html_error_template with a Template containing UTF-8 99 chars""" 100 101 code = """# -*- coding: utf-8 -*- 102% if 2 == 2: /an error 103${'привет'} 104% endif 105""" 106 try: 107 template = Template(code) 108 template.render_unicode() 109 except exceptions.CompileException: 110 html_error = exceptions.html_error_template().render() 111 assert ( 112 "CompileException: Fragment 'if 2 == 2: /an " 113 "error' is not a partial control statement " 114 "at line: 2 char: 1" 115 ).encode( 116 sys.getdefaultencoding(), "htmlentityreplace" 117 ) in html_error 118 assert ( 119 "${'привет'}".encode( 120 sys.getdefaultencoding(), "htmlentityreplace" 121 ) 122 in html_error 123 ) 124 else: 125 assert False, ( 126 "This function should trigger a CompileException, " 127 "but didn't" 128 ) 129 130 def test_format_closures(self): 131 try: 132 exec("def foo():" " raise RuntimeError('test')", locals()) 133 foo() # noqa 134 except: 135 html_error = exceptions.html_error_template().render() 136 assert "RuntimeError: test" in str(html_error) 137 138 def test_py_utf8_html_error_template(self): 139 try: 140 foo = "日本" # noqa 141 raise RuntimeError("test") 142 except: 143 html_error = exceptions.html_error_template().render() 144 assert "RuntimeError: test" in html_error.decode("utf-8") 145 assert "foo = "日本"" in html_error.decode( 146 "utf-8" 147 ) or "foo = "日本"" in html_error.decode("utf-8") 148 149 def test_py_unicode_error_html_error_template(self): 150 try: 151 raise RuntimeError("日本") 152 except: 153 html_error = exceptions.html_error_template().render() 154 assert "RuntimeError: 日本".encode("ascii", "ignore") in html_error 155 156 @requires_pygments_14 157 def test_format_exceptions_pygments(self): 158 l = TemplateLookup(format_exceptions=True) 159 160 l.put_string( 161 "foo.html", 162 """ 163<%inherit file="base.html"/> 164${foobar} 165 """, 166 ) 167 168 l.put_string( 169 "base.html", 170 """ 171 ${self.body()} 172 """, 173 ) 174 175 assert ( 176 '<table class="syntax-highlightedtable">' 177 in l.get_template("foo.html").render_unicode() 178 ) 179 180 @requires_no_pygments_exceptions 181 def test_format_exceptions_no_pygments(self): 182 l = TemplateLookup(format_exceptions=True) 183 184 l.put_string( 185 "foo.html", 186 """ 187<%inherit file="base.html"/> 188${foobar} 189 """, 190 ) 191 192 l.put_string( 193 "base.html", 194 """ 195 ${self.body()} 196 """, 197 ) 198 199 assert '<div class="sourceline">${foobar}</div>' in result_lines( 200 l.get_template("foo.html").render_unicode() 201 ) 202 203 @requires_pygments_14 204 def test_utf8_format_exceptions_pygments(self): 205 """test that htmlentityreplace formatting is applied to 206 exceptions reported with format_exceptions=True""" 207 208 l = TemplateLookup(format_exceptions=True) 209 l.put_string( 210 "foo.html", """# -*- coding: utf-8 -*-\n${'привет' + foobar}""" 211 ) 212 213 assert "'привет'</span>" in l.get_template( 214 "foo.html" 215 ).render().decode("utf-8") 216 217 @requires_no_pygments_exceptions 218 def test_utf8_format_exceptions_no_pygments(self): 219 """test that htmlentityreplace formatting is applied to 220 exceptions reported with format_exceptions=True""" 221 222 l = TemplateLookup(format_exceptions=True) 223 l.put_string( 224 "foo.html", """# -*- coding: utf-8 -*-\n${'привет' + foobar}""" 225 ) 226 227 assert ( 228 '<div class="sourceline">${'привет' + foobar}</div>' 229 in result_lines( 230 l.get_template("foo.html").render().decode("utf-8") 231 ) 232 ) 233 234 def test_mod_no_encoding(self): 235 mod = __import__("test.foo.mod_no_encoding").foo.mod_no_encoding 236 try: 237 mod.run() 238 except: 239 t, v, tback = sys.exc_info() 240 exceptions.html_error_template().render_unicode( 241 error=v, traceback=tback 242 ) 243 244 def test_custom_tback(self): 245 try: 246 raise RuntimeError("error 1") 247 foo("bar") # noqa 248 except: 249 t, v, tback = sys.exc_info() 250 251 try: 252 raise RuntimeError("error 2") 253 except: 254 html_error = exceptions.html_error_template().render_unicode( 255 error=v, traceback=tback 256 ) 257 258 # obfuscate the text so that this text 259 # isn't in the 'wrong' exception 260 assert ( 261 "".join(reversed(");touq&rab;touq&(oof")) in html_error 262 or "".join(reversed(");43#&rab;43#&(oof")) in html_error 263 ) 264 265 def test_tback_no_trace_from_py_file(self): 266 try: 267 t = self._file_template("runtimeerr.html") 268 t.render() 269 except: 270 t, v, tback = sys.exc_info() 271 272 # and don't even send what we have. 273 html_error = exceptions.html_error_template().render_unicode( 274 error=v, traceback=None 275 ) 276 277 assert self.indicates_unbound_local_error(html_error, "y") 278 279 def test_tback_trace_from_py_file(self): 280 t = self._file_template("runtimeerr.html") 281 try: 282 t.render() 283 assert False 284 except: 285 html_error = exceptions.html_error_template().render_unicode() 286 287 assert self.indicates_unbound_local_error(html_error, "y") 288 289 def test_code_block_line_number(self): 290 l = TemplateLookup() 291 l.put_string( 292 "foo.html", 293 """ 294<% 295msg = "Something went wrong." 296raise RuntimeError(msg) # This is the line. 297%> 298 """, 299 ) 300 t = l.get_template("foo.html") 301 try: 302 t.render() 303 except: 304 text_error = exceptions.text_error_template().render_unicode() 305 assert 'File "foo.html", line 4, in render_body' in text_error 306 assert "raise RuntimeError(msg) # This is the line." in text_error 307 else: 308 assert False 309 310 def test_module_block_line_number(self): 311 l = TemplateLookup() 312 l.put_string( 313 "foo.html", 314 """ 315<%! 316def foo(): 317 msg = "Something went wrong." 318 raise RuntimeError(msg) # This is the line. 319%> 320${foo()} 321 """, 322 ) 323 t = l.get_template("foo.html") 324 try: 325 t.render() 326 except: 327 text_error = exceptions.text_error_template().render_unicode() 328 assert 'File "foo.html", line 7, in render_body' in text_error 329 assert 'File "foo.html", line 5, in foo' in text_error 330 assert "raise RuntimeError(msg) # This is the line." in text_error 331 else: 332 assert False 333 334 def test_alternating_file_names(self): 335 l = TemplateLookup() 336 l.put_string( 337 "base.html", 338 """ 339<%! 340def broken(): 341 raise RuntimeError("Something went wrong.") 342%> body starts here 343<%block name="foo"> 344 ${broken()} 345</%block> 346 """, 347 ) 348 l.put_string( 349 "foo.html", 350 """ 351<%inherit file="base.html"/> 352<%block name="foo"> 353 ${parent.foo()} 354</%block> 355 """, 356 ) 357 t = l.get_template("foo.html") 358 try: 359 t.render() 360 except: 361 text_error = exceptions.text_error_template().render_unicode() 362 assert ( 363 """ 364 File "base.html", line 5, in render_body 365 %> body starts here 366 File "foo.html", line 4, in render_foo 367 ${parent.foo()} 368 File "base.html", line 7, in render_foo 369 ${broken()} 370 File "base.html", line 4, in broken 371 raise RuntimeError("Something went wrong.") 372""" 373 in text_error 374 ) 375 else: 376 assert False 377