@@ -2524,6 +2524,150 @@ def test_poutput_all_keyword_args(outsim_app):
25242524 assert "My string" in out
25252525
25262526
2527+ @pytest .mark .parametrize (
2528+ 'stream' ,
2529+ ['stdout' , 'stderr' ],
2530+ )
2531+ @pytest .mark .parametrize (
2532+ ('emoji' , 'markup' , 'highlight' ),
2533+ [
2534+ (True , True , True ),
2535+ (False , False , False ),
2536+ (True , False , True ),
2537+ ],
2538+ )
2539+ def test_create_base_printing_console_caching (
2540+ base_app : cmd2 .Cmd , stream : str , emoji : bool , markup : bool , highlight : bool
2541+ ) -> None :
2542+ """Test that base printing consoles are cached and reused when settings match."""
2543+ file = sys .stderr if stream == 'stderr' else base_app .stdout
2544+
2545+ # Initial creation
2546+ console1 = base_app ._create_base_printing_console (
2547+ file = file ,
2548+ emoji = emoji ,
2549+ markup = markup ,
2550+ highlight = highlight ,
2551+ )
2552+
2553+ # Verify it's in the cache
2554+ cached = getattr (base_app ._console_cache , stream )
2555+ assert cached is console1
2556+
2557+ # Identical request should return the same object
2558+ console2 = base_app ._create_base_printing_console (
2559+ file = file ,
2560+ emoji = emoji ,
2561+ markup = markup ,
2562+ highlight = highlight ,
2563+ )
2564+ assert console2 is console1
2565+
2566+
2567+ @pytest .mark .parametrize (
2568+ 'stream' ,
2569+ ['stdout' , 'stderr' ],
2570+ )
2571+ def test_create_base_printing_console_invalidation (base_app : cmd2 .Cmd , stream : str ) -> None :
2572+ """Test that changing settings, theme, or ALLOW_STYLE invalidates the cache."""
2573+ file = sys .stderr if stream == 'stderr' else base_app .stdout
2574+
2575+ # Initial creation
2576+ console1 = base_app ._create_base_printing_console (
2577+ file = file ,
2578+ emoji = True ,
2579+ markup = True ,
2580+ highlight = True ,
2581+ )
2582+
2583+ # Changing emoji should create a new console
2584+ console2 = base_app ._create_base_printing_console (
2585+ file = file ,
2586+ emoji = False ,
2587+ markup = True ,
2588+ highlight = True ,
2589+ )
2590+ assert console2 is not console1
2591+ assert getattr (base_app ._console_cache , stream ) is console2
2592+
2593+ # Changing markup should create a new console
2594+ console3 = base_app ._create_base_printing_console (
2595+ file = file ,
2596+ emoji = False ,
2597+ markup = False ,
2598+ highlight = True ,
2599+ )
2600+ assert console3 is not console2
2601+ assert getattr (base_app ._console_cache , stream ) is console3
2602+
2603+ # Changing highlight should create a new console
2604+ console4 = base_app ._create_base_printing_console (
2605+ file = file ,
2606+ emoji = False ,
2607+ markup = False ,
2608+ highlight = False ,
2609+ )
2610+ assert console4 is not console3
2611+ assert getattr (base_app ._console_cache , stream ) is console4
2612+
2613+ # Changing ALLOW_STYLE should create a new console
2614+ orig_allow_style = ru .ALLOW_STYLE
2615+ try :
2616+ ru .ALLOW_STYLE = ru .AllowStyle .ALWAYS if orig_allow_style != ru .AllowStyle .ALWAYS else ru .AllowStyle .NEVER
2617+ console5 = base_app ._create_base_printing_console (
2618+ file = file ,
2619+ emoji = False ,
2620+ markup = False ,
2621+ highlight = False ,
2622+ )
2623+ assert console5 is not console4
2624+ assert getattr (base_app ._console_cache , stream ) is console5
2625+ finally :
2626+ ru .ALLOW_STYLE = orig_allow_style
2627+
2628+ # Changing the theme should create a new console
2629+ from rich .theme import Theme
2630+
2631+ old_theme = ru .APP_THEME
2632+ try :
2633+ ru .APP_THEME = Theme ()
2634+ console6 = base_app ._create_base_printing_console (
2635+ file = file ,
2636+ emoji = False ,
2637+ markup = False ,
2638+ highlight = False ,
2639+ )
2640+ assert console6 is not console5
2641+ assert getattr (base_app ._console_cache , stream ) is console6
2642+ finally :
2643+ ru .APP_THEME = old_theme
2644+
2645+
2646+ def test_create_base_printing_console_non_cached (base_app : cmd2 .Cmd ) -> None :
2647+ """Test that arbitrary file objects are not cached."""
2648+ file = io .StringIO ()
2649+
2650+ console1 = base_app ._create_base_printing_console (
2651+ file = file ,
2652+ emoji = True ,
2653+ markup = True ,
2654+ highlight = True ,
2655+ )
2656+
2657+ # Cache for stdout/stderr should still be None (assuming they haven't been touched yet)
2658+ assert base_app ._console_cache .stdout is None
2659+ assert base_app ._console_cache .stderr is None
2660+
2661+ # A second request for the same file should still create a new object
2662+ console2 = base_app ._create_base_printing_console (
2663+ file = file ,
2664+ emoji = True ,
2665+ markup = True ,
2666+ highlight = True ,
2667+ )
2668+ assert console2 is not console1
2669+
2670+
25272671def test_broken_pipe_error (outsim_app , monkeypatch , capsys ):
25282672 write_mock = mock .MagicMock ()
25292673 write_mock .side_effect = BrokenPipeError
0 commit comments