OLD | NEW |
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 """ | 2 """ |
3 jinja2.debug | 3 jinja2.debug |
4 ~~~~~~~~~~~~ | 4 ~~~~~~~~~~~~ |
5 | 5 |
6 Implements the debug interface for Jinja. This module does some pretty | 6 Implements the debug interface for Jinja. This module does some pretty |
7 ugly stuff with the Python traceback system in order to achieve tracebacks | 7 ugly stuff with the Python traceback system in order to achieve tracebacks |
8 with correct line numbers, locals and contents. | 8 with correct line numbers, locals and contents. |
9 | 9 |
10 :copyright: (c) 2010 by the Jinja Team. | 10 :copyright: (c) 2010 by the Jinja Team. |
11 :license: BSD, see LICENSE for more details. | 11 :license: BSD, see LICENSE for more details. |
12 """ | 12 """ |
13 import sys | 13 import sys |
14 import traceback | 14 import traceback |
15 from types import TracebackType | 15 from types import TracebackType, CodeType |
16 from jinja2.utils import missing, internal_code | 16 from jinja2.utils import missing, internal_code |
17 from jinja2.exceptions import TemplateSyntaxError | 17 from jinja2.exceptions import TemplateSyntaxError |
18 from jinja2._compat import iteritems, reraise, code_type | 18 from jinja2._compat import iteritems, reraise, PY2 |
19 | 19 |
20 # on pypy we can take advantage of transparent proxies | 20 # on pypy we can take advantage of transparent proxies |
21 try: | 21 try: |
22 from __pypy__ import tproxy | 22 from __pypy__ import tproxy |
23 except ImportError: | 23 except ImportError: |
24 tproxy = None | 24 tproxy = None |
25 | 25 |
26 | 26 |
27 # how does the raise helper look like? | 27 # how does the raise helper look like? |
28 try: | 28 try: |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 if tb is None: | 238 if tb is None: |
239 location = 'template' | 239 location = 'template' |
240 else: | 240 else: |
241 function = tb.tb_frame.f_code.co_name | 241 function = tb.tb_frame.f_code.co_name |
242 if function == 'root': | 242 if function == 'root': |
243 location = 'top-level template code' | 243 location = 'top-level template code' |
244 elif function.startswith('block_'): | 244 elif function.startswith('block_'): |
245 location = 'block "%s"' % function[6:] | 245 location = 'block "%s"' % function[6:] |
246 else: | 246 else: |
247 location = 'template' | 247 location = 'template' |
248 code = code_type(0, code.co_nlocals, code.co_stacksize, | 248 |
249 code.co_flags, code.co_code, code.co_consts, | 249 if PY2: |
250 code.co_names, code.co_varnames, filename, | 250 code = CodeType(0, code.co_nlocals, code.co_stacksize, |
251 location, code.co_firstlineno, | 251 code.co_flags, code.co_code, code.co_consts, |
252 code.co_lnotab, (), ()) | 252 code.co_names, code.co_varnames, filename, |
253 except: | 253 location, code.co_firstlineno, |
| 254 code.co_lnotab, (), ()) |
| 255 else: |
| 256 code = CodeType(0, code.co_kwonlyargcount, |
| 257 code.co_nlocals, code.co_stacksize, |
| 258 code.co_flags, code.co_code, code.co_consts, |
| 259 code.co_names, code.co_varnames, filename, |
| 260 location, code.co_firstlineno, |
| 261 code.co_lnotab, (), ()) |
| 262 except Exception as e: |
254 pass | 263 pass |
255 | 264 |
256 # execute the code and catch the new traceback | 265 # execute the code and catch the new traceback |
257 try: | 266 try: |
258 exec(code, globals, locals) | 267 exec(code, globals, locals) |
259 except: | 268 except: |
260 exc_info = sys.exc_info() | 269 exc_info = sys.exc_info() |
261 new_tb = exc_info[2].tb_next | 270 new_tb = exc_info[2].tb_next |
262 | 271 |
263 # return without this frame | 272 # return without this frame |
264 return exc_info[:2] + (new_tb,) | 273 return exc_info[:2] + (new_tb,) |
265 | 274 |
266 | 275 |
267 def _init_ugly_crap(): | 276 def _init_ugly_crap(): |
268 """This function implements a few ugly things so that we can patch the | 277 """This function implements a few ugly things so that we can patch the |
269 traceback objects. The function returned allows resetting `tb_next` on | 278 traceback objects. The function returned allows resetting `tb_next` on |
270 any python traceback object. Do not attempt to use this on non cpython | 279 any python traceback object. Do not attempt to use this on non cpython |
271 interpreters | 280 interpreters |
272 """ | 281 """ |
273 import ctypes | 282 import ctypes |
274 from types import TracebackType | 283 from types import TracebackType |
275 | 284 |
276 # figure out side of _Py_ssize_t | 285 if PY2: |
277 if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'): | 286 # figure out size of _Py_ssize_t for Python 2: |
278 _Py_ssize_t = ctypes.c_int64 | 287 if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'): |
| 288 _Py_ssize_t = ctypes.c_int64 |
| 289 else: |
| 290 _Py_ssize_t = ctypes.c_int |
279 else: | 291 else: |
280 _Py_ssize_t = ctypes.c_int | 292 # platform ssize_t on Python 3 |
| 293 _Py_ssize_t = ctypes.c_ssize_t |
281 | 294 |
282 # regular python | 295 # regular python |
283 class _PyObject(ctypes.Structure): | 296 class _PyObject(ctypes.Structure): |
284 pass | 297 pass |
285 _PyObject._fields_ = [ | 298 _PyObject._fields_ = [ |
286 ('ob_refcnt', _Py_ssize_t), | 299 ('ob_refcnt', _Py_ssize_t), |
287 ('ob_type', ctypes.POINTER(_PyObject)) | 300 ('ob_type', ctypes.POINTER(_PyObject)) |
288 ] | 301 ] |
289 | 302 |
290 # python with trace | 303 # python with trace |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 | 341 |
329 # try to get a tb_set_next implementation if we don't have transparent | 342 # try to get a tb_set_next implementation if we don't have transparent |
330 # proxies. | 343 # proxies. |
331 tb_set_next = None | 344 tb_set_next = None |
332 if tproxy is None: | 345 if tproxy is None: |
333 try: | 346 try: |
334 tb_set_next = _init_ugly_crap() | 347 tb_set_next = _init_ugly_crap() |
335 except: | 348 except: |
336 pass | 349 pass |
337 del _init_ugly_crap | 350 del _init_ugly_crap |
OLD | NEW |