@@ -475,10 +475,14 @@ class TracebackException:
475
475
occurred.
476
476
- :attr:`lineno` For syntax errors - the linenumber where the error
477
477
occurred.
478
+ - :attr:`end_lineno` For syntax errors - the end linenumber where the error
479
+ occurred. Can be `None` if not present.
478
480
- :attr:`text` For syntax errors - the text where the error
479
481
occurred.
480
482
- :attr:`offset` For syntax errors - the offset into the text where the
481
483
error occurred.
484
+ - :attr:`end_offset` For syntax errors - the offset into the text where the
485
+ error occurred. Can be `None` if not present.
482
486
- :attr:`msg` For syntax errors - the compiler error message.
483
487
"""
484
488
@@ -507,8 +511,11 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None,
507
511
self .filename = exc_value .filename
508
512
lno = exc_value .lineno
509
513
self .lineno = str (lno ) if lno is not None else None
514
+ end_lno = exc_value .end_lineno
515
+ self .end_lineno = str (end_lno ) if end_lno is not None else None
510
516
self .text = exc_value .text
511
517
self .offset = exc_value .offset
518
+ self .end_offset = exc_value .end_offset
512
519
self .msg = exc_value .msg
513
520
if lookup_lines :
514
521
self ._load_lines ()
@@ -623,12 +630,20 @@ def _format_syntax_error(self, stype):
623
630
ltext = rtext .lstrip (' \n \f ' )
624
631
spaces = len (rtext ) - len (ltext )
625
632
yield ' {}\n ' .format (ltext )
626
- # Convert 1-based column offset to 0-based index into stripped text
627
- caret = (self .offset or 0 ) - 1 - spaces
628
- if caret >= 0 :
629
- # non-space whitespace (likes tabs) must be kept for alignment
630
- caretspace = ((c if c .isspace () else ' ' ) for c in ltext [:caret ])
631
- yield ' {}^\n ' .format ('' .join (caretspace ))
633
+
634
+ if self .offset is not None :
635
+ offset = self .offset
636
+ end_offset = self .end_offset if self .end_offset is not None else offset
637
+ if offset == end_offset or end_offset == - 1 :
638
+ end_offset = offset + 1
639
+
640
+ # Convert 1-based column offset to 0-based index into stripped text
641
+ colno = offset - 1 - spaces
642
+ end_colno = end_offset - 1 - spaces
643
+ if colno >= 0 :
644
+ # non-space whitespace (likes tabs) must be kept for alignment
645
+ caretspace = ((c if c .isspace () else ' ' ) for c in ltext [:colno ])
646
+ yield ' {}{}' .format ("" .join (caretspace ), ('^' * (end_colno - colno ) + "\n " ))
632
647
msg = self .msg or "<no detail available>"
633
648
yield "{}: {}{}\n " .format (stype , msg , filename_suffix )
634
649
0 commit comments