@@ -633,3 +633,116 @@ def get_scores() -> dict[str, int]:
633633 # Test converted result
634634 result = await manager .call_tool ("get_scores" , {})
635635 assert result == expected
636+
637+
638+ class TestRemoveTools :
639+ """Test tool removal functionality in the tool manager."""
640+
641+ def test_remove_existing_tool (self ):
642+ """Test removing an existing tool."""
643+
644+ def add (a : int , b : int ) -> int :
645+ """Add two numbers."""
646+ return a + b
647+
648+ manager = ToolManager ()
649+ manager .add_tool (add )
650+
651+ # Verify tool exists
652+ assert manager .get_tool ("add" ) is not None
653+ assert len (manager .list_tools ()) == 1
654+
655+ # Remove the tool - should not raise any exception
656+ manager .remove_tool ("add" )
657+
658+ # Verify tool is removed
659+ assert manager .get_tool ("add" ) is None
660+ assert len (manager .list_tools ()) == 0
661+
662+ def test_remove_nonexistent_tool (self ):
663+ """Test removing a non-existent tool raises ToolError."""
664+ manager = ToolManager ()
665+
666+ with pytest .raises (ToolError , match = "Unknown tool: nonexistent" ):
667+ manager .remove_tool ("nonexistent" )
668+
669+ def test_remove_tool_from_multiple_tools (self ):
670+ """Test removing one tool when multiple tools exist."""
671+
672+ def add (a : int , b : int ) -> int :
673+ """Add two numbers."""
674+ return a + b
675+
676+ def multiply (a : int , b : int ) -> int :
677+ """Multiply two numbers."""
678+ return a * b
679+
680+ def divide (a : int , b : int ) -> float :
681+ """Divide two numbers."""
682+ return a / b
683+
684+ manager = ToolManager ()
685+ manager .add_tool (add )
686+ manager .add_tool (multiply )
687+ manager .add_tool (divide )
688+
689+ # Verify all tools exist
690+ assert len (manager .list_tools ()) == 3
691+ assert manager .get_tool ("add" ) is not None
692+ assert manager .get_tool ("multiply" ) is not None
693+ assert manager .get_tool ("divide" ) is not None
694+
695+ # Remove middle tool
696+ manager .remove_tool ("multiply" )
697+
698+ # Verify only multiply is removed
699+ assert len (manager .list_tools ()) == 2
700+ assert manager .get_tool ("add" ) is not None
701+ assert manager .get_tool ("multiply" ) is None
702+ assert manager .get_tool ("divide" ) is not None
703+
704+ @pytest .mark .anyio
705+ async def test_call_removed_tool_raises_error (self ):
706+ """Test that calling a removed tool raises ToolError."""
707+
708+ def greet (name : str ) -> str :
709+ """Greet someone."""
710+ return f"Hello, { name } !"
711+
712+ manager = ToolManager ()
713+ manager .add_tool (greet )
714+
715+ # Verify tool works before removal
716+ result = await manager .call_tool ("greet" , {"name" : "World" })
717+ assert result == "Hello, World!"
718+
719+ # Remove the tool
720+ manager .remove_tool ("greet" )
721+
722+ # Verify calling removed tool raises error
723+ with pytest .raises (ToolError , match = "Unknown tool: greet" ):
724+ await manager .call_tool ("greet" , {"name" : "World" })
725+
726+ def test_remove_tool_case_sensitive (self ):
727+ """Test that tool removal is case-sensitive."""
728+
729+ def test_func () -> str :
730+ """Test function."""
731+ return "test"
732+
733+ manager = ToolManager ()
734+ manager .add_tool (test_func )
735+
736+ # Verify tool exists
737+ assert manager .get_tool ("test_func" ) is not None
738+
739+ # Try to remove with different case - should raise ToolError
740+ with pytest .raises (ToolError , match = "Unknown tool: Test_Func" ):
741+ manager .remove_tool ("Test_Func" )
742+
743+ # Verify original tool still exists
744+ assert manager .get_tool ("test_func" ) is not None
745+
746+ # Remove with correct case
747+ manager .remove_tool ("test_func" )
748+ assert manager .get_tool ("test_func" ) is None
0 commit comments