debug.py (7542B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\jinja2\debug.py 2 import sys 3 import traceback 4 from types import TracebackType 5 from jinja2.utils import CodeType, missing, internal_code 6 from jinja2.exceptions import TemplateSyntaxError 7 try: 8 from __pypy__ import tproxy 9 except ImportError: 10 tproxy = None 11 12 try: 13 exec "raise TypeError, 'foo'" 14 except SyntaxError: 15 raise_helper = 'raise __jinja_exception__[1]' 16 except TypeError: 17 raise_helper = 'raise __jinja_exception__[0], __jinja_exception__[1]' 18 19 class TracebackFrameProxy(object): 20 21 def __init__(self, tb): 22 self.tb = tb 23 self._tb_next = None 24 25 @property 26 def tb_next(self): 27 return self._tb_next 28 29 def set_next(self, next): 30 if tb_set_next is not None: 31 try: 32 tb_set_next(self.tb, next and next.tb or None) 33 except Exception: 34 pass 35 36 self._tb_next = next 37 38 @property 39 def is_jinja_frame(self): 40 return '__jinja_template__' in self.tb.tb_frame.f_globals 41 42 def __getattr__(self, name): 43 return getattr(self.tb, name) 44 45 46 def make_frame_proxy(frame): 47 proxy = TracebackFrameProxy(frame) 48 if tproxy is None: 49 return proxy 50 51 def operation_handler(operation, *args, **kwargs): 52 if operation in ('__getattribute__', '__getattr__'): 53 return getattr(proxy, args[0]) 54 if operation == '__setattr__': 55 proxy.__setattr__(*args, **kwargs) 56 else: 57 return getattr(proxy, operation)(*args, **kwargs) 58 59 return tproxy(TracebackType, operation_handler) 60 61 62 class ProcessedTraceback(object): 63 64 def __init__(self, exc_type, exc_value, frames): 65 self.exc_type = exc_type 66 self.exc_value = exc_value 67 self.frames = frames 68 prev_tb = None 69 for tb in self.frames: 70 if prev_tb is not None: 71 prev_tb.set_next(tb) 72 prev_tb = tb 73 74 prev_tb.set_next(None) 75 76 def render_as_text(self, limit = None): 77 lines = traceback.format_exception(self.exc_type, self.exc_value, self.frames[0], limit=limit) 78 return ''.join(lines).rstrip() 79 80 def render_as_html(self, full = False): 81 from jinja2.debugrenderer import render_traceback 82 return u'%s\n\n<!--\n%s\n-->' % (render_traceback(self, full=full), self.render_as_text().decode('utf-8', 'replace')) 83 84 @property 85 def is_template_syntax_error(self): 86 return isinstance(self.exc_value, TemplateSyntaxError) 87 88 @property 89 def exc_info(self): 90 return (self.exc_type, self.exc_value, self.frames[0]) 91 92 @property 93 def standard_exc_info(self): 94 tb = self.frames[0] 95 if type(tb) is not TracebackType: 96 tb = tb.tb 97 return (self.exc_type, self.exc_value, tb) 98 99 100 def make_traceback(exc_info, source_hint = None): 101 exc_type, exc_value, tb = exc_info 102 if isinstance(exc_value, TemplateSyntaxError): 103 exc_info = translate_syntax_error(exc_value, source_hint) 104 initial_skip = 0 105 else: 106 initial_skip = 1 107 return translate_exception(exc_info, initial_skip) 108 109 110 def translate_syntax_error(error, source = None): 111 error.source = source 112 error.translated = True 113 exc_info = (error.__class__, error, None) 114 filename = error.filename 115 if filename is None: 116 filename = '<unknown>' 117 return fake_exc_info(exc_info, filename, error.lineno) 118 119 120 def translate_exception(exc_info, initial_skip = 0): 121 tb = exc_info[2] 122 frames = [] 123 for x in xrange(initial_skip): 124 if tb is not None: 125 tb = tb.tb_next 126 127 initial_tb = tb 128 while tb is not None: 129 if tb.tb_frame.f_code in internal_code: 130 tb = tb.tb_next 131 continue 132 next = tb.tb_next 133 template = tb.tb_frame.f_globals.get('__jinja_template__') 134 if template is not None: 135 lineno = template.get_corresponding_lineno(tb.tb_lineno) 136 tb = fake_exc_info(exc_info[:2] + (tb,), template.filename, lineno)[2] 137 frames.append(make_frame_proxy(tb)) 138 tb = next 139 140 if not frames: 141 raise exc_info[0], exc_info[1], exc_info[2] 142 return ProcessedTraceback(exc_info[0], exc_info[1], frames) 143 144 145 def fake_exc_info(exc_info, filename, lineno): 146 exc_type, exc_value, tb = exc_info 147 if tb is not None: 148 real_locals = tb.tb_frame.f_locals.copy() 149 ctx = real_locals.get('context') 150 if ctx: 151 locals = ctx.get_all() 152 else: 153 locals = {} 154 for name, value in real_locals.iteritems(): 155 if name.startswith('l_') and value is not missing: 156 locals[name[2:]] = value 157 158 locals.pop('__jinja_exception__', None) 159 else: 160 locals = {} 161 globals = {'__name__': filename, 162 '__file__': filename, 163 '__jinja_exception__': exc_info[:2], 164 '__jinja_template__': None} 165 code = compile('\n' * (lineno - 1) + raise_helper, filename, 'exec') 166 try: 167 if tb is None: 168 location = 'template' 169 else: 170 function = tb.tb_frame.f_code.co_name 171 if function == 'root': 172 location = 'top-level template code' 173 elif function.startswith('block_'): 174 location = 'block "%s"' % function[6:] 175 else: 176 location = 'template' 177 code = CodeType(0, code.co_nlocals, code.co_stacksize, code.co_flags, code.co_code, code.co_consts, code.co_names, code.co_varnames, filename, location, code.co_firstlineno, code.co_lnotab, (), ()) 178 except: 179 pass 180 181 try: 182 exec code in globals, locals 183 except: 184 exc_info = sys.exc_info() 185 new_tb = exc_info[2].tb_next 186 187 return exc_info[:2] + (new_tb,) 188 189 190 def _init_ugly_crap(): 191 import ctypes 192 from types import TracebackType 193 if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'): 194 _Py_ssize_t = ctypes.c_int64 195 else: 196 _Py_ssize_t = ctypes.c_int 197 198 class _PyObject(ctypes.Structure): 199 pass 200 201 _PyObject._fields_ = [('ob_refcnt', _Py_ssize_t), ('ob_type', ctypes.POINTER(_PyObject))] 202 if hasattr(sys, 'getobjects'): 203 204 class _PyObject(ctypes.Structure): 205 pass 206 207 _PyObject._fields_ = [('_ob_next', ctypes.POINTER(_PyObject)), 208 ('_ob_prev', ctypes.POINTER(_PyObject)), 209 ('ob_refcnt', _Py_ssize_t), 210 ('ob_type', ctypes.POINTER(_PyObject))] 211 212 class _Traceback(_PyObject): 213 pass 214 215 _Traceback._fields_ = [('tb_next', ctypes.POINTER(_Traceback)), 216 ('tb_frame', ctypes.POINTER(_PyObject)), 217 ('tb_lasti', ctypes.c_int), 218 ('tb_lineno', ctypes.c_int)] 219 220 def tb_set_next(tb, next): 221 if not (isinstance(tb, TracebackType) and (next is None or isinstance(next, TracebackType))): 222 raise TypeError('tb_set_next arguments must be traceback objects') 223 obj = _Traceback.from_address(id(tb)) 224 if tb.tb_next is not None: 225 old = _Traceback.from_address(id(tb.tb_next)) 226 old.ob_refcnt -= 1 227 if next is None: 228 obj.tb_next = ctypes.POINTER(_Traceback)() 229 else: 230 next = _Traceback.from_address(id(next)) 231 next.ob_refcnt += 1 232 obj.tb_next = ctypes.pointer(next) 233 234 return tb_set_next 235 236 237 tb_set_next = None 238 if tproxy is None: 239 try: 240 from jinja2._debugsupport import tb_set_next 241 except ImportError: 242 try: 243 tb_set_next = _init_ugly_crap() 244 except: 245 pass 246 247 del _init_ugly_crap