@@ -5416,6 +5416,93 @@ def expected(t, m, fn, l, f, E, e, z, n):
54165416 ]
54175417 self .assertEqual (actual , expected (** colors ))
54185418
5419+ def test_colorized_traceback_unicode (self ):
5420+ try :
5421+ 啊哈 = 1 ; 啊哈 / 0 ####
5422+ except Exception as e :
5423+ exc = traceback .TracebackException .from_exception (e )
5424+
5425+ actual = "" .join (exc .format (colorize = True )).splitlines ()
5426+ def expected (t , m , fn , l , f , E , e , z , n ):
5427+ return [
5428+ f" 啊哈=1; { e } 啊哈{ z } { E } /{ z } { e } 0{ z } ####" ,
5429+ f" { e } ~~~~{ z } { E } ^{ z } { e } ~{ z } " ,
5430+ ]
5431+ self .assertEqual (actual [2 :4 ], expected (** colors ))
5432+
5433+ try :
5434+ ééééé / 0
5435+ except Exception as e :
5436+ exc = traceback .TracebackException .from_exception (e )
5437+
5438+ actual = "" .join (exc .format (colorize = True )).splitlines ()
5439+ def expected (t , m , fn , l , f , E , e , z , n ):
5440+ return [
5441+ f" { E } ééééé{ z } /0" ,
5442+ f" { E } ^^^^^{ z } " ,
5443+ ]
5444+ self .assertEqual (actual [2 :4 ], expected (** colors ))
5445+
5446+ def test_colorized_syntax_error_ascii_display_width (self ):
5447+ """Caret alignment for ASCII edge cases handled by _wlen.
5448+
5449+ The old ASCII fast track in _display_width returned the raw character
5450+ offset for ASCII strings, which is wrong for CTRL-Z (display width 2)
5451+ and ANSI escape sequences (display width 0).
5452+ """
5453+ E = colors ["E" ]
5454+ z = colors ["z" ]
5455+ t = colors ["t" ]
5456+ m = colors ["m" ]
5457+ fn = colors ["fn" ]
5458+ l = colors ["l" ]
5459+
5460+ def _make_syntax_error (text , offset , end_offset ):
5461+ err = SyntaxError ("invalid syntax" )
5462+ err .filename = "<string>"
5463+ err .lineno = 1
5464+ err .end_lineno = 1
5465+ err .text = text
5466+ err .offset = offset
5467+ err .end_offset = end_offset
5468+ return err
5469+
5470+ # CTRL-Z (\x1a) is ASCII but displayed as ^Z (2 columns).
5471+ # Verify caret aligns when CTRL-Z precedes the error.
5472+ err = _make_syntax_error ("a\x1a $\n " , offset = 3 , end_offset = 4 )
5473+ exc = traceback .TracebackException .from_exception (err )
5474+ actual = "" .join (exc .format (colorize = True ))
5475+ # 'a' (1 col) + '\x1a' (2 cols) = 3 cols before '$'
5476+ self .assertIn (
5477+ f' File { fn } "<string>"{ z } , line { l } 1{ z } \n '
5478+ f' a\x1a { E } ${ z } \n '
5479+ f' { " " * 3 } { E } ^{ z } \n '
5480+ f'{ t } SyntaxError{ z } : { m } invalid syntax{ z } \n ' ,
5481+ actual ,
5482+ )
5483+
5484+ # CTRL-Z in the highlighted (error) region counts as 2 columns.
5485+ err = _make_syntax_error ("$\x1a \n " , offset = 1 , end_offset = 3 )
5486+ exc = traceback .TracebackException .from_exception (err )
5487+ actual = "" .join (exc .format (colorize = True ))
5488+ # '$' (1 col) + '\x1a' (2 cols) = 3 columns of carets
5489+ self .assertIn (
5490+ f' { E } $\x1a { z } \n '
5491+ f' { E } { "^" * 3 } { z } \n ' ,
5492+ actual ,
5493+ )
5494+
5495+ # ANSI escape sequences are ASCII but take 0 display columns.
5496+ err = _make_syntax_error ("a\x1b [1mb$\n " , offset = 7 , end_offset = 8 )
5497+ exc = traceback .TracebackException .from_exception (err )
5498+ actual = "" .join (exc .format (colorize = True ))
5499+ # 'a' (1 col) + '\x1b[1m' (0 cols) + 'b' (1 col) = 2 before '$'
5500+ self .assertIn (
5501+ f' a\x1b [1mb{ E } ${ z } \n '
5502+ f' { " " * 2 } { E } ^{ z } \n ' ,
5503+ actual ,
5504+ )
5505+
54195506
54205507class TestShowLines (unittest .TestCase ):
54215508 """Tests for the show_source_lines parameter in traceback formatting functions."""
@@ -5654,92 +5741,7 @@ def f2():
56545741 f1pos = result .index (", in f1" )
56555742 f2pos = result .index (", in f2" )
56565743 self .assertLess (f1pos , f2pos , "f1 should be printed before f2" )
5657- def test_colorized_traceback_unicode (self ):
5658- try :
5659- 啊哈 = 1 ; 啊哈 / 0 ####
5660- except Exception as e :
5661- exc = traceback .TracebackException .from_exception (e )
5662-
5663- actual = "" .join (exc .format (colorize = True )).splitlines ()
5664- def expected (t , m , fn , l , f , E , e , z , n ):
5665- return [
5666- f" 啊哈=1; { e } 啊哈{ z } { E } /{ z } { e } 0{ z } ####" ,
5667- f" { e } ~~~~{ z } { E } ^{ z } { e } ~{ z } " ,
5668- ]
5669- self .assertEqual (actual [2 :4 ], expected (** colors ))
5670-
5671- try :
5672- ééééé / 0
5673- except Exception as e :
5674- exc = traceback .TracebackException .from_exception (e )
5675-
5676- actual = "" .join (exc .format (colorize = True )).splitlines ()
5677- def expected (t , m , fn , l , f , E , e , z , n ):
5678- return [
5679- f" { E } ééééé{ z } /0" ,
5680- f" { E } ^^^^^{ z } " ,
5681- ]
5682- self .assertEqual (actual [2 :4 ], expected (** colors ))
5683-
5684- def test_colorized_syntax_error_ascii_display_width (self ):
5685- """Caret alignment for ASCII edge cases handled by _wlen.
5686-
5687- The old ASCII fast track in _display_width returned the raw character
5688- offset for ASCII strings, which is wrong for CTRL-Z (display width 2)
5689- and ANSI escape sequences (display width 0).
5690- """
5691- E = colors ["E" ]
5692- z = colors ["z" ]
5693- t = colors ["t" ]
5694- m = colors ["m" ]
5695- fn = colors ["fn" ]
5696- l = colors ["l" ]
5697-
5698- def _make_syntax_error (text , offset , end_offset ):
5699- err = SyntaxError ("invalid syntax" )
5700- err .filename = "<string>"
5701- err .lineno = 1
5702- err .end_lineno = 1
5703- err .text = text
5704- err .offset = offset
5705- err .end_offset = end_offset
5706- return err
5707-
5708- # CTRL-Z (\x1a) is ASCII but displayed as ^Z (2 columns).
5709- # Verify caret aligns when CTRL-Z precedes the error.
5710- err = _make_syntax_error ("a\x1a $\n " , offset = 3 , end_offset = 4 )
5711- exc = traceback .TracebackException .from_exception (err )
5712- actual = "" .join (exc .format (colorize = True ))
5713- # 'a' (1 col) + '\x1a' (2 cols) = 3 cols before '$'
5714- self .assertIn (
5715- f' File { fn } "<string>"{ z } , line { l } 1{ z } \n '
5716- f' a\x1a { E } ${ z } \n '
5717- f' { " " * 3 } { E } ^{ z } \n '
5718- f'{ t } SyntaxError{ z } : { m } invalid syntax{ z } \n ' ,
5719- actual ,
5720- )
57215744
5722- # CTRL-Z in the highlighted (error) region counts as 2 columns.
5723- err = _make_syntax_error ("$\x1a \n " , offset = 1 , end_offset = 3 )
5724- exc = traceback .TracebackException .from_exception (err )
5725- actual = "" .join (exc .format (colorize = True ))
5726- # '$' (1 col) + '\x1a' (2 cols) = 3 columns of carets
5727- self .assertIn (
5728- f' { E } $\x1a { z } \n '
5729- f' { E } { "^" * 3 } { z } \n ' ,
5730- actual ,
5731- )
5732-
5733- # ANSI escape sequences are ASCII but take 0 display columns.
5734- err = _make_syntax_error ("a\x1b [1mb$\n " , offset = 7 , end_offset = 8 )
5735- exc = traceback .TracebackException .from_exception (err )
5736- actual = "" .join (exc .format (colorize = True ))
5737- # 'a' (1 col) + '\x1b[1m' (0 cols) + 'b' (1 col) = 2 before '$'
5738- self .assertIn (
5739- f' a\x1b [1mb{ E } ${ z } \n '
5740- f' { " " * 2 } { E } ^{ z } \n ' ,
5741- actual ,
5742- )
57435745
57445746class TestLazyImportSuggestions (unittest .TestCase ):
57455747 """Test that lazy imports are not reified when computing AttributeError suggestions."""
0 commit comments