11"""Tests for Rich encoding fix to handle surrogate characters."""
22
33from io import StringIO
4+ from typing import Any
45from unittest .mock import MagicMock
56
67from rich .console import Console
1314
1415def create_strict_encoding_console () -> tuple [Console , StringIO ]:
1516 """Create a Console that enforces strict UTF-8 encoding, simulating Windows console behavior.
16-
17+
1718 When Rich writes to the console, the file object needs to encode strings to bytes.
1819 With errors='strict' (default for TextIOWrapper), this raises UnicodeEncodeError on surrogates.
1920 This function simulates that behavior to test the encoding fix.
2021 """
2122 buffer = StringIO ()
22-
23+
2324 class StrictEncodingWrapper :
2425 def __init__ (self , file_obj : StringIO ) -> None :
2526 self ._file = file_obj
26-
27+
2728 def write (self , text : str ) -> int :
2829 """Validate encoding before writing to simulate strict encoding behavior."""
2930 text .encode ('utf-8' )
3031 return self ._file .write (text )
31-
32+
3233 def flush (self ) -> None :
3334 self ._file .flush ()
34-
35+
3536 def isatty (self ) -> bool :
3637 return False
37-
38- def __getattr__ (self , name : str ):
38+
39+ def __getattr__ (self , name : str ) -> Any :
3940 # Delegate all other attributes to the underlying file
4041 return getattr (self ._file , name )
41-
42+
4243 strict_file = StrictEncodingWrapper (buffer )
4344 console = Console (file = strict_file , width = 80 , force_terminal = False )
4445 return console , buffer
4546
4647
4748def test_rich_printer_handles_surrogate_characters_in_violation_card () -> None :
4849 """Test that RichPrinter._print_violation_card() handles surrogate characters without errors.
49-
50+
5051 The error occurs in Rich's console._write_buffer() -> write() when console.print() is called.
5152 On Windows with strict encoding, this raises UnicodeEncodeError on surrogates.
5253 """
@@ -57,7 +58,7 @@ def test_rich_printer_handles_surrogate_characters_in_violation_card() -> None:
5758 content = document_content ,
5859 is_git_diff_format = False ,
5960 )
60-
61+
6162 detection = Detection (
6263 detection_type_id = 'test-id' ,
6364 type = 'test-type' ,
@@ -72,14 +73,14 @@ def test_rich_printer_handles_surrogate_characters_in_violation_card() -> None:
7273 detection_rule_id = 'test-rule-id' ,
7374 severity = 'Medium' ,
7475 )
75-
76+
7677 mock_ctx = MagicMock ()
7778 mock_ctx .obj = {
7879 'scan_type' : consts .SAST_SCAN_TYPE ,
7980 'show_secret' : False ,
8081 }
8182 mock_ctx .info_name = consts .SAST_SCAN_TYPE
82-
83+
8384 console , _ = create_strict_encoding_console ()
8485 printer = RichPrinter (mock_ctx , console , console )
8586 printer ._print_violation_card (document , detection , 1 , 1 )
0 commit comments