@@ -726,22 +726,68 @@ def test_print_stderr_non_jupyter():
726726def test_print_stderr_jupyter ():
727727 """Test stderr printing when in Jupyter using IPython display."""
728728 # Mock the Jupyter detection and IPython display
729+ # We need to mock the import inside the function since IPython may not be installed
730+ mock_html_class = MagicMock ()
731+ mock_display_func = MagicMock ()
732+
733+ # Create a mock module structure that matches "from IPython.display import HTML, display"
734+ mock_display_module = MagicMock ()
735+ mock_display_module .HTML = mock_html_class
736+ mock_display_module .display = mock_display_func
737+
738+ # Create mock IPython module with display submodule
739+ mock_ipython_module = MagicMock ()
740+ mock_ipython_module .display = mock_display_module
741+
742+ original_import = __import__
743+
744+ def mock_import (name , globals = None , locals = None , fromlist = (), level = 0 ):
745+ if name == "IPython.display" :
746+ return mock_display_module
747+ if name == "IPython" :
748+ return mock_ipython_module
749+ # For other imports, use real import
750+ return original_import (name , globals , locals , fromlist , level )
751+
729752 with patch ("mcp.client.stdio._is_jupyter_notebook" , return_value = True ), patch (
730- "IPython.display.display"
731- ) as mock_display , patch ( "IPython.display.HTML" ) as mock_html :
753+ "builtins.__import__" , side_effect = mock_import
754+ ):
732755 _print_stderr ("test error message" , sys .stderr )
733756
734757 # Verify IPython display was called
735- mock_html .assert_called_once ()
736- mock_display .assert_called_once ()
758+ mock_html_class .assert_called_once ()
759+ mock_display_func .assert_called_once ()
737760
738761
739762def test_print_stderr_jupyter_fallback ():
740763 """Test stderr printing falls back to regular print if IPython display fails."""
741764 stderr_capture = io .StringIO ()
765+
766+ # Mock IPython import to raise exception on display
767+ mock_html_class = MagicMock ()
768+ mock_display_func = MagicMock (side_effect = Exception ("Display failed" ))
769+
770+ # Create a mock module structure that matches "from IPython.display import HTML, display"
771+ mock_display_module = MagicMock ()
772+ mock_display_module .HTML = mock_html_class
773+ mock_display_module .display = mock_display_func
774+
775+ # Create mock IPython module with display submodule
776+ mock_ipython_module = MagicMock ()
777+ mock_ipython_module .display = mock_display_module
778+
779+ original_import = __import__
780+
781+ def mock_import (name , globals = None , locals = None , fromlist = (), level = 0 ):
782+ if name == "IPython.display" :
783+ return mock_display_module
784+ if name == "IPython" :
785+ return mock_ipython_module
786+ # For other imports, use real import
787+ return original_import (name , globals , locals , fromlist , level )
742788
743789 with patch ("mcp.client.stdio._is_jupyter_notebook" , return_value = True ), patch (
744- "IPython.display.display " , side_effect = Exception ( "Display failed" )
790+ "builtins.__import__ " , side_effect = mock_import
745791 ):
746792 _print_stderr ("test error message" , stderr_capture )
747793
0 commit comments