Completely drop RootModel from types module (#1910)

This commit is contained in:
Marcelo Trylesinski 2026-01-19 14:29:15 +01:00 • committed by GitHub
commit 5fdd48a0d3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 640 additions and 800 deletions

View file

@ -77,14 +77,14 @@ class NotificationCollector:
) -> None:
"""Handle any server notification and route to appropriate handler."""
if isinstance(message, ServerNotification): # pragma: no branch
if isinstance(message.root, ProgressNotification):
self.progress_notifications.append(message.root.params)
elif isinstance(message.root, LoggingMessageNotification):
self.log_messages.append(message.root.params)
elif isinstance(message.root, ResourceListChangedNotification):
self.resource_notifications.append(message.root.params)
elif isinstance(message.root, ToolListChangedNotification): # pragma: no cover
self.tool_notifications.append(message.root.params)
if isinstance(message, ProgressNotification):
self.progress_notifications.append(message.params)
elif isinstance(message, LoggingMessageNotification):
self.log_messages.append(message.params)
elif isinstance(message, ResourceListChangedNotification):
self.resource_notifications.append(message.params)
elif isinstance(message, ToolListChangedNotification): # pragma: no cover
self.tool_notifications.append(message.params)
# Common fixtures

View file

@ -41,8 +41,8 @@ async def test_list_prompts_basic() -> None:
result = await handler(request)
assert isinstance(result, ServerResult)
assert isinstance(result.root, ListPromptsResult)
assert result.root.prompts == test_prompts
assert isinstance(result, ListPromptsResult)
assert result.prompts == test_prompts
@pytest.mark.anyio
@ -67,8 +67,8 @@ async def test_list_resources_basic() -> None:
result = await handler(request)
assert isinstance(result, ServerResult)
assert isinstance(result.root, ListResourcesResult)
assert result.root.resources == test_resources
assert isinstance(result, ListResourcesResult)
assert result.resources == test_resources
@pytest.mark.anyio
@ -114,8 +114,8 @@ async def test_list_tools_basic() -> None:
result = await handler(request)
assert isinstance(result, ServerResult)
assert isinstance(result.root, ListToolsResult)
assert result.root.tools == test_tools
assert isinstance(result, ListToolsResult)
assert result.tools == test_tools
@pytest.mark.anyio
@ -135,8 +135,8 @@ async def test_list_prompts_empty() -> None:
result = await handler(request)
assert isinstance(result, ServerResult)
assert isinstance(result.root, ListPromptsResult)
assert result.root.prompts == []
assert isinstance(result, ListPromptsResult)
assert result.prompts == []
@pytest.mark.anyio
@ -156,8 +156,8 @@ async def test_list_resources_empty() -> None:
result = await handler(request)
assert isinstance(result, ServerResult)
assert isinstance(result.root, ListResourcesResult)
assert result.root.resources == []
assert isinstance(result, ListResourcesResult)
assert result.resources == []
@pytest.mark.anyio
@ -177,5 +177,5 @@ async def test_list_tools_empty() -> None:
result = await handler(request)
assert isinstance(result, ServerResult)
assert isinstance(result.root, ListToolsResult)
assert result.root.tools == []
assert isinstance(result, ListToolsResult)
assert result.tools == []

View file

@ -15,8 +15,6 @@ from mcp.types import (
CallToolResult,
CancelledNotification,
CancelledNotificationParams,
ClientNotification,
ClientRequest,
Tool,
)
@ -59,11 +57,7 @@ async def test_server_remains_functional_after_cancel():
async def first_request():
try:
await client.session.send_request(
ClientRequest(
CallToolRequest(
params=CallToolRequestParams(name="test_tool", arguments={}),
)
),
CallToolRequest(params=CallToolRequestParams(name="test_tool", arguments={})),
CallToolResult,
)
pytest.fail("First request should have been cancelled") # pragma: no cover
@ -80,13 +74,8 @@ async def test_server_remains_functional_after_cancel():
# Cancel it
assert first_request_id is not None
await client.session.send_notification(
ClientNotification(
CancelledNotification(
params=CancelledNotificationParams(
request_id=first_request_id,
reason="Testing server recovery",
),
)
CancelledNotification(
params=CancelledNotificationParams(request_id=first_request_id, reason="Testing server recovery"),
)
)

View file

@ -60,7 +60,7 @@ async def test_normal_message_handling_not_affected():
# Create a mock RequestResponder
responder = Mock(spec=RequestResponder)
responder.request = types.ClientRequest(root=types.PingRequest(method="ping"))
responder.request = types.PingRequest(method="ping")
responder.__enter__ = Mock(return_value=responder)
responder.__exit__ = Mock(return_value=None)

View file

@ -39,10 +39,10 @@ async def test_read_resource_text(temp_file: Path):
# Call the handler
result = await handler(request)
assert isinstance(result.root, types.ReadResourceResult)
assert len(result.root.contents) == 1
assert isinstance(result, types.ReadResourceResult)
assert len(result.contents) == 1
content = result.root.contents[0]
content = result.contents[0]
assert isinstance(content, types.TextResourceContents)
assert content.text == "Hello World"
assert content.mime_type == "text/plain"
@ -66,10 +66,10 @@ async def test_read_resource_binary(temp_file: Path):
# Call the handler
result = await handler(request)
assert isinstance(result.root, types.ReadResourceResult)
assert len(result.root.contents) == 1
assert isinstance(result, types.ReadResourceResult)
assert len(result.contents) == 1
content = result.root.contents[0]
content = result.contents[0]
assert isinstance(content, types.BlobResourceContents)
assert content.mime_type == "application/octet-stream"
@ -97,10 +97,10 @@ async def test_read_resource_default_mime(temp_file: Path):
# Call the handler
result = await handler(request)
assert isinstance(result.root, types.ReadResourceResult)
assert len(result.root.contents) == 1
assert isinstance(result, types.ReadResourceResult)
assert len(result.contents) == 1
content = result.root.contents[0]
content = result.contents[0]
assert isinstance(content, types.TextResourceContents)
assert content.text == "Hello World"
assert content.mime_type == "text/plain"

View file

@ -60,7 +60,7 @@ async def test_server_session_initialize():
raise message
if isinstance(message, ClientNotification) and isinstance(
message.root, InitializedNotification
message, InitializedNotification
): # pragma: no branch
received_initialized = True
return
@ -158,7 +158,7 @@ async def test_server_session_initialize_with_older_protocol_version():
raise message
if isinstance(message, types.ClientNotification) and isinstance(
message.root, InitializedNotification
message, InitializedNotification
): # pragma: no branch
received_initialized = True
return
@ -236,11 +236,11 @@ async def test_ping_request_before_initialization():
# We should receive a ping request before initialization
if isinstance(message, RequestResponder) and isinstance(
message.request.root, types.PingRequest
message.request, types.PingRequest
): # pragma: no branch
# Respond to the ping
with message:
await message.respond(types.ServerResult(types.EmptyResult()))
await message.respond(types.EmptyResult())
return
async def mock_client():

View file

@ -57,27 +57,25 @@ async def test_request_immediately_after_initialize_response():
# Handle tools/list request
if isinstance(message, RequestResponder):
if isinstance(message.request.root, types.ListToolsRequest): # pragma: no branch
if isinstance(message.request, types.ListToolsRequest): # pragma: no branch
tools_list_success = True
# Respond with a tool list
with message:
await message.respond(
types.ServerResult(
types.ListToolsResult(
tools=[
Tool(
name="example_tool",
description="An example tool",
input_schema={"type": "object", "properties": {}},
)
]
)
types.ListToolsResult(
tools=[
Tool(
name="example_tool",
description="An example tool",
input_schema={"type": "object", "properties": {}},
)
]
)
)
# Handle InitializedNotification
if isinstance(message, types.ClientNotification):
if isinstance(message.root, types.InitializedNotification): # pragma: no branch
if isinstance(message, types.InitializedNotification): # pragma: no branch
# Done - exit gracefully
return