10
10
import tokenize
11
11
import traceback
12
12
13
+ if sys .version_info >= (3 , 11 ):
13
14
14
- def is_exception_group (exc ):
15
- return isinstance (exc , ExceptionGroup )
15
+ def is_exception_group (exc ):
16
+ return isinstance (exc , ExceptionGroup )
17
+
18
+ else :
19
+ try :
20
+ from exceptiongroup import ExceptionGroup
21
+ except ImportError :
22
+
23
+ def is_exception_group (exc ):
24
+ return False
25
+
26
+ else :
27
+
28
+ def is_exception_group (exc ):
29
+ return isinstance (exc , ExceptionGroup )
16
30
17
31
18
32
class SyntaxHighlighter :
@@ -31,7 +45,7 @@ class SyntaxHighlighter:
31
45
32
46
_builtins = set (dir (builtins ))
33
47
_constants = {"True" , "False" , "None" }
34
- _punctation = {"(" , ")" , "[" , "]" , "{" , "}" , ":" , "," , ";" }
48
+ _punctuation = {"(" , ")" , "[" , "]" , "{" , "}" , ":" , "," , ";" }
35
49
_strings = {tokenize .STRING }
36
50
_fstring_middle = None
37
51
@@ -65,7 +79,7 @@ def highlight(self, source):
65
79
else :
66
80
color = style ["identifier" ]
67
81
elif type_ == tokenize .OP :
68
- if string in self ._punctation :
82
+ if string in self ._punctuation :
69
83
color = style ["punctuation" ]
70
84
else :
71
85
color = style ["operator" ]
@@ -441,31 +455,31 @@ def _format_exception(
441
455
# on the indentation; the preliminary context for "SyntaxError" is always indented, while
442
456
# the Exception itself is not. This allows us to identify the correct index for the
443
457
# exception message.
444
- error_message_index = 0
445
- for error_message_index , part in enumerate (exception_only ): # noqa: B007
446
- if not part .startswith (" " ):
447
- break
448
-
449
- error_message = exception_only [error_message_index ][:- 1 ] # Remove last new line temporarily
450
-
451
- if self ._colorize :
452
- if ":" in error_message :
453
- exception_type , exception_value = error_message .split (":" , 1 )
454
- exception_type = self ._theme ["exception_type" ].format (exception_type )
455
- exception_value = self ._theme ["exception_value" ].format (exception_value )
456
- error_message = exception_type + ":" + exception_value
457
- else :
458
- error_message = self ._theme ["exception_type" ].format (error_message )
458
+ no_indented_indexes = (i for i , p in enumerate (exception_only ) if not p .startswith (" " ))
459
+ error_message_index = next (no_indented_indexes , None )
459
460
460
- if self ._diagnose and frames :
461
- if issubclass (exc_type , AssertionError ) and not str (exc_value ) and final_source :
462
- if self ._colorize :
463
- final_source = self ._syntax_highlighter .highlight (final_source )
464
- error_message += ": " + final_source
461
+ if error_message_index is not None :
462
+ # Remove final new line temporarily.
463
+ error_message = exception_only [error_message_index ][:- 1 ]
464
+
465
+ if self ._colorize :
466
+ if ":" in error_message :
467
+ exception_type , exception_value = error_message .split (":" , 1 )
468
+ exception_type = self ._theme ["exception_type" ].format (exception_type )
469
+ exception_value = self ._theme ["exception_value" ].format (exception_value )
470
+ error_message = exception_type + ":" + exception_value
471
+ else :
472
+ error_message = self ._theme ["exception_type" ].format (error_message )
473
+
474
+ if self ._diagnose and frames :
475
+ if issubclass (exc_type , AssertionError ) and not str (exc_value ) and final_source :
476
+ if self ._colorize :
477
+ final_source = self ._syntax_highlighter .highlight (final_source )
478
+ error_message += ": " + final_source
465
479
466
- error_message = "\n " + error_message
480
+ error_message = "\n " + error_message
467
481
468
- exception_only [error_message_index ] = error_message + "\n "
482
+ exception_only [error_message_index ] = error_message + "\n "
469
483
470
484
if is_first :
471
485
yield self ._prefix
@@ -484,7 +498,7 @@ def _format_exception(
484
498
else :
485
499
yield from self ._indent (introduction + "\n " , group_nesting )
486
500
487
- frames_lines = traceback . format_list (frames ) + exception_only
501
+ frames_lines = self . _format_list (frames ) + exception_only
488
502
if self ._colorize or self ._backtrace or self ._diagnose :
489
503
frames_lines = self ._format_locations (frames_lines , has_introduction = has_introduction )
490
504
@@ -512,5 +526,15 @@ def _format_exception(
512
526
if not is_exception_group (exc ) or group_nesting == 10 :
513
527
yield from self ._indent ("-" * 35 , group_nesting + 1 , prefix = "+-" )
514
528
529
+ def _format_list (self , frames ):
530
+ result = []
531
+ for filename , lineno , name , line in frames :
532
+ row = []
533
+ row .append (' File "{}", line {}, in {}\n ' .format (filename , lineno , name ))
534
+ if line :
535
+ row .append (" {}\n " .format (line .strip ()))
536
+ result .append ("" .join (row ))
537
+ return result
538
+
515
539
def format_exception (self , type_ , value , tb , * , from_decorator = False ):
516
540
yield from self ._format_exception (value , tb , is_first = True , from_decorator = from_decorator )
0 commit comments