Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd79d365

Browse files
Port new specializations to traceback.py
Co-authored-by: Batuhan Taskaya <batuhanosmantaskaya@gmail.com>
1 parent0a825ea commitd79d365

File tree

3 files changed

+106
-4
lines changed

3 files changed

+106
-4
lines changed

‎Doc/library/traceback.rst‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ The output for the example would look similar to this:
473473
['Traceback (most recent call last):\n',
474474
' File "<doctest default[0]>", line 10, in <module>\n lumberjack()\n ^^^^^^^^^^^^\n',
475475
' File "<doctest default[0]>", line 4, in lumberjack\n bright_side_of_death()\n ^^^^^^^^^^^^^^^^^^^^^^\n',
476-
' File "<doctest default[0]>", line 7, in bright_side_of_death\n return tuple()[0]\n^^^^^^^^^^\n',
476+
' File "<doctest default[0]>", line 7, in bright_side_of_death\n return tuple()[0]\n~~~~~~~^^^\n',
477477
'IndexError: tuple index out of range\n']
478478
*** extract_tb:
479479
[<FrameSummary file <doctest...>, line 10 in <module>>,
@@ -482,7 +482,7 @@ The output for the example would look similar to this:
482482
*** format_tb:
483483
[' File "<doctest default[0]>", line 10, in <module>\n lumberjack()\n ^^^^^^^^^^^^\n',
484484
' File "<doctest default[0]>", line 4, in lumberjack\n bright_side_of_death()\n ^^^^^^^^^^^^^^^^^^^^^^\n',
485-
' File "<doctest default[0]>", line 7, in bright_side_of_death\n return tuple()[0]\n^^^^^^^^^^\n']
485+
' File "<doctest default[0]>", line 7, in bright_side_of_death\n return tuple()[0]\n~~~~~~~^^^\n']
486486
*** tb_lineno: 10
487487

488488

‎Lib/test/test_traceback.py‎

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,61 @@ def f_with_multiline():
406406
result_lines=self.get_exception(f_with_multiline)
407407
self.assertEqual(result_lines,expected_f.splitlines())
408408

409+
deftest_caret_for_binary_operators(self):
410+
deff_with_binary_operator():
411+
divisor=20
412+
return10+divisor/0+30
413+
414+
lineno_f=f_with_binary_operator.__code__.co_firstlineno
415+
expected_error= (
416+
'Traceback (most recent call last):\n'
417+
f' File "{__file__}", line{self.callable_line}, in get_exception\n'
418+
' callable()\n'
419+
' ^^^^^^^^^^\n'
420+
f' File "{__file__}", line{lineno_f+2}, in f_with_binary_operator\n'
421+
' return 10 + divisor / 0 + 30\n'
422+
' ~~~~~~~~^~~\n'
423+
)
424+
result_lines=self.get_exception(f_with_binary_operator)
425+
self.assertEqual(result_lines,expected_error.splitlines())
426+
427+
deftest_caret_for_binary_operators_two_char(self):
428+
deff_with_binary_operator():
429+
divisor=20
430+
return10+divisor//0+30
431+
432+
lineno_f=f_with_binary_operator.__code__.co_firstlineno
433+
expected_error= (
434+
'Traceback (most recent call last):\n'
435+
f' File "{__file__}", line{self.callable_line}, in get_exception\n'
436+
' callable()\n'
437+
' ^^^^^^^^^^\n'
438+
f' File "{__file__}", line{lineno_f+2}, in f_with_binary_operator\n'
439+
' return 10 + divisor // 0 + 30\n'
440+
' ~~~~~~~~^^~~\n'
441+
)
442+
result_lines=self.get_exception(f_with_binary_operator)
443+
self.assertEqual(result_lines,expected_error.splitlines())
444+
445+
deftest_caret_for_subscript(self):
446+
deff_with_subscript():
447+
some_dict= {'x': {'y':None}}
448+
returnsome_dict['x']['y']['z']
449+
450+
lineno_f=f_with_subscript.__code__.co_firstlineno
451+
expected_error= (
452+
'Traceback (most recent call last):\n'
453+
f' File "{__file__}", line{self.callable_line}, in get_exception\n'
454+
' callable()\n'
455+
' ^^^^^^^^^^\n'
456+
f' File "{__file__}", line{lineno_f+2}, in f_with_subscript\n'
457+
" return some_dict['x']['y']['z']\n"
458+
' ~~~~~~~~~~~~~~~~~~~^^^^^\n'
459+
)
460+
result_lines=self.get_exception(f_with_subscript)
461+
self.assertEqual(result_lines,expected_error.splitlines())
462+
463+
409464

410465
@cpython_only
411466
@requires_debug_ranges()
@@ -1615,7 +1670,7 @@ def f():
16151670
self.assertEqual(
16161671
output.getvalue().split('\n')[-5:],
16171672
[' x/0',
1618-
'^^^',
1673+
'~^~',
16191674
' x = 12',
16201675
'ZeroDivisionError: division by zero',
16211676
''])

‎Lib/traceback.py‎

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,23 @@ def format(self):
494494
colno=_byte_offset_to_character_offset(frame._original_line,frame.colno)
495495
end_colno=_byte_offset_to_character_offset(frame._original_line,frame.end_colno)
496496

497+
try:
498+
anchors=_extract_caret_anchors_from_line_segment(
499+
frame._original_line[colno-1:end_colno]
500+
)
501+
exceptException:
502+
anchors=None
503+
497504
row.append(' ')
498505
row.append(' '* (colno-stripped_characters))
499-
row.append('^'* (end_colno-colno))
506+
507+
ifanchors:
508+
row.append('~'* (anchors[0]))
509+
row.append('^'* (anchors[1]-anchors[0]))
510+
row.append('~'* (end_colno-colno-anchors[1]))
511+
else:
512+
row.append('^'* (end_colno-colno))
513+
500514
row.append('\n')
501515

502516
ifframe.locals:
@@ -520,6 +534,39 @@ def _byte_offset_to_character_offset(str, offset):
520534
returnlen(as_utf8[:offset+1].decode("utf-8"))
521535

522536

537+
def_extract_caret_anchors_from_line_segment(segment):
538+
importast
539+
540+
try:
541+
tree=ast.parse(segment)
542+
exceptSyntaxError:
543+
returnNone
544+
545+
iflen(tree.body)!=1:
546+
returnNone
547+
548+
statement=tree.body[0]
549+
matchstatement:
550+
caseast.Expr(expr):
551+
matchexpr:
552+
caseast.BinOp():
553+
operator_str=segment[expr.left.end_col_offset:expr.right.col_offset]
554+
operator_offset=len(operator_str)-len(operator_str.lstrip())
555+
556+
left_anchor=expr.left.end_col_offset+operator_offset
557+
right_anchor=left_anchor+1
558+
if (
559+
operator_offset+1<len(operator_str)
560+
andnotoperator_str[operator_offset+1].isspace()
561+
):
562+
right_anchor+=1
563+
returnleft_anchor,right_anchor
564+
caseast.Subscript():
565+
returnexpr.value.end_col_offset,expr.slice.end_col_offset+1
566+
567+
returnNone
568+
569+
523570
classTracebackException:
524571
"""An exception ready for rendering.
525572

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp