##// END OF EJS Templates
Refactor of coloring and traceback mechanism....
Matthias Bussonnier -
Show More
@@ -374,16 +374,32 b' def _fixed_getinnerframes(etb, context=1, tb_offset=0):'
374 # (SyntaxErrors have to be treated specially because they have no traceback)
374 # (SyntaxErrors have to be treated specially because they have no traceback)
375
375
376
376
377 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_format=(lambda x,_:x,None)):
377 def _format_traceback_lines(lnum, index, lines, Colors, lvals, _line_format):
378 """
379 Format tracebacks lines with pointing arrow, leading numbers...
380
381 Parameters
382 ==========
383
384 lnum: int
385 index: int
386 lines: list[string]
387 Colors:
388 ColorScheme used.
389 lvals: bytes
390 Values of local variables, already colored, to inject just after the error line.
391 _line_format: f (str) -> (str, bool)
392 return (colorized version of str, failure to do so)
393 """
378 numbers_width = INDENT_SIZE - 1
394 numbers_width = INDENT_SIZE - 1
379 res = []
395 res = []
380 i = lnum - index
381
396
382 for line in lines:
397 for i,line in enumerate(lines, lnum-index):
383 line = py3compat.cast_unicode(line)
398 line = py3compat.cast_unicode(line)
384
399
385 new_line, err = _line_format(line, 'str')
400 new_line, err = _line_format(line, 'str')
386 if not err: line = new_line
401 if not err:
402 line = new_line
387
403
388 if i == lnum:
404 if i == lnum:
389 # This is the line with the error
405 # This is the line with the error
@@ -399,7 +415,6 b' def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_forma'
399 res.append(line)
415 res.append(line)
400 if lvals and i == lnum:
416 if lvals and i == lnum:
401 res.append(lvals + '\n')
417 res.append(lvals + '\n')
402 i = i + 1
403 return res
418 return res
404
419
405 def is_recursion_error(etype, value, records):
420 def is_recursion_error(etype, value, records):
@@ -869,7 +884,7 b' class VerboseTB(TBTools):'
869
884
870 file = py3compat.cast_unicode(file, util_path.fs_encoding)
885 file = py3compat.cast_unicode(file, util_path.fs_encoding)
871 link = tpl_link % util_path.compress_user(file)
886 link = tpl_link % util_path.compress_user(file)
872 args, varargs, varkw, locals = inspect.getargvalues(frame)
887 args, varargs, varkw, locals_ = inspect.getargvalues(frame)
873
888
874 if func == '?':
889 if func == '?':
875 call = ''
890 call = ''
@@ -879,7 +894,7 b' class VerboseTB(TBTools):'
879 try:
894 try:
880 call = tpl_call % (func, inspect.formatargvalues(args,
895 call = tpl_call % (func, inspect.formatargvalues(args,
881 varargs, varkw,
896 varargs, varkw,
882 locals, formatvalue=var_repr))
897 locals_, formatvalue=var_repr))
883 except KeyError:
898 except KeyError:
884 # This happens in situations like errors inside generator
899 # This happens in situations like errors inside generator
885 # expressions, where local variables are listed in the
900 # expressions, where local variables are listed in the
@@ -968,14 +983,15 b' class VerboseTB(TBTools):'
968 unique_names = uniq_stable(names)
983 unique_names = uniq_stable(names)
969
984
970 # Start loop over vars
985 # Start loop over vars
971 lvals = []
986 lvals = ''
987 lvals_list = []
972 if self.include_vars:
988 if self.include_vars:
973 for name_full in unique_names:
989 for name_full in unique_names:
974 name_base = name_full.split('.', 1)[0]
990 name_base = name_full.split('.', 1)[0]
975 if name_base in frame.f_code.co_varnames:
991 if name_base in frame.f_code.co_varnames:
976 if name_base in locals:
992 if name_base in locals_:
977 try:
993 try:
978 value = repr(eval(name_full, locals))
994 value = repr(eval(name_full, locals_))
979 except:
995 except:
980 value = undefined
996 value = undefined
981 else:
997 else:
@@ -990,11 +1006,9 b' class VerboseTB(TBTools):'
990 else:
1006 else:
991 value = undefined
1007 value = undefined
992 name = tpl_global_var % name_full
1008 name = tpl_global_var % name_full
993 lvals.append(tpl_name_val % (name, value))
1009 lvals_list.append(tpl_name_val % (name, value))
994 if lvals:
1010 if lvals_list:
995 lvals = '%s%s' % (indent, em_normal.join(lvals))
1011 lvals = '%s%s' % (indent, em_normal.join(lvals_list))
996 else:
997 lvals = ''
998
1012
999 level = '%s %s\n' % (link, call)
1013 level = '%s %s\n' % (link, call)
1000
1014
@@ -213,7 +213,7 b' class Parser(Colorable):'
213
213
214 string_output = 0
214 string_output = 0
215 if out == 'str' or self.out == 'str' or \
215 if out == 'str' or self.out == 'str' or \
216 isinstance(self.out,StringIO):
216 isinstance(self.out, StringIO):
217 # XXX - I don't really like this state handling logic, but at this
217 # XXX - I don't really like this state handling logic, but at this
218 # point I don't want to make major changes, so adding the
218 # point I don't want to make major changes, so adding the
219 # isinstance() check is the simplest I can do to ensure correct
219 # isinstance() check is the simplest I can do to ensure correct
@@ -223,6 +223,8 b' class Parser(Colorable):'
223 string_output = 1
223 string_output = 1
224 elif out is not None:
224 elif out is not None:
225 self.out = out
225 self.out = out
226 else:
227 raise ValueError('`out` or `self.out` should be file-like or the value `"str"`')
226
228
227 # Fast return of the unmodified input for NoColor scheme
229 # Fast return of the unmodified input for NoColor scheme
228 if self.style == 'NoColor':
230 if self.style == 'NoColor':
@@ -275,12 +277,13 b' class Parser(Colorable):'
275 return (output, error)
277 return (output, error)
276 return (None, error)
278 return (None, error)
277
279
278 def __call__(self, toktype, toktext, start_pos, end_pos, line):
280 def _inner_call_(self, toktype, toktext, start_pos, end_pos, line):
279 """ Token handler, with syntax highlighting."""
281 """like call but write to a temporary buffer"""
282 buff = StringIO()
280 (srow,scol) = start_pos
283 (srow,scol) = start_pos
281 (erow,ecol) = end_pos
284 (erow,ecol) = end_pos
282 colors = self.colors
285 colors = self.colors
283 owrite = self.out.write
286 owrite = buff.write
284
287
285 # line separator, so this works across platforms
288 # line separator, so this works across platforms
286 linesep = os.linesep
289 linesep = os.linesep
@@ -297,7 +300,8 b' class Parser(Colorable):'
297 # skip indenting tokens
300 # skip indenting tokens
298 if toktype in [token.INDENT, token.DEDENT]:
301 if toktype in [token.INDENT, token.DEDENT]:
299 self.pos = newpos
302 self.pos = newpos
300 return
303 buff.seek(0)
304 return buff.read()
301
305
302 # map token type to a color group
306 # map token type to a color group
303 if token.LPAR <= toktype <= token.OP:
307 if token.LPAR <= toktype <= token.OP:
@@ -316,3 +320,12 b' class Parser(Colorable):'
316
320
317 # send text
321 # send text
318 owrite('%s%s%s' % (color,toktext,colors.normal))
322 owrite('%s%s%s' % (color,toktext,colors.normal))
323 buff.seek(0)
324 return buff.read()
325
326
327 def __call__(self, toktype, toktext, start_pos, end_pos, line):
328 """ Token handler, with syntax highlighting."""
329 self.out.write(
330 self._inner_call_(toktype, toktext, start_pos, end_pos, line))
331
General Comments 0
You need to be logged in to leave comments. Login now