ci: add strict-no-cover to detect unnecessary coverage pragmas (#1897)
This commit is contained in:
parent
3cfdea0e97
commit
a7ddfdae07
30 changed files with 355 additions and 358 deletions
|
|
@ -23,7 +23,7 @@ class MockTokenStorage:
|
|||
self._tokens: OAuthToken | None = None
|
||||
self._client_info: OAuthClientInformationFull | None = None
|
||||
|
||||
async def get_tokens(self) -> OAuthToken | None: # pragma: no cover
|
||||
async def get_tokens(self) -> OAuthToken | None:
|
||||
return self._tokens
|
||||
|
||||
async def set_tokens(self, tokens: OAuthToken) -> None: # pragma: no cover
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class StreamSpyCollection:
|
|||
self.client.sent_messages.clear()
|
||||
self.server.sent_messages.clear()
|
||||
|
||||
def get_client_requests(self, method: str | None = None) -> list[JSONRPCRequest]: # pragma: no cover
|
||||
def get_client_requests(self, method: str | None = None) -> list[JSONRPCRequest]:
|
||||
"""Get client-sent requests, optionally filtered by method."""
|
||||
return [
|
||||
req.message
|
||||
|
|
|
|||
|
|
@ -1696,7 +1696,7 @@ class TestSEP985Discovery:
|
|||
final_response = httpx.Response(200, request=final_request)
|
||||
try:
|
||||
await auth_flow.asend(final_response)
|
||||
except StopAsyncIteration: # pragma: no cover
|
||||
except StopAsyncIteration:
|
||||
pass
|
||||
|
||||
@pytest.mark.anyio
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ def non_sdk_server(non_sdk_server_port: int) -> Generator[None, None, None]:
|
|||
proc.start()
|
||||
|
||||
# Wait for server to be ready
|
||||
try: # pragma: no cover
|
||||
try:
|
||||
wait_for_server(non_sdk_server_port, timeout=10.0)
|
||||
except TimeoutError: # pragma: no cover
|
||||
proc.kill()
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ async def test_stdio_client_universal_cleanup():
|
|||
|
||||
@pytest.mark.anyio
|
||||
@pytest.mark.skipif(sys.platform == "win32", reason="Windows signal handling is different")
|
||||
async def test_stdio_client_sigint_only_process(): # pragma: no cover
|
||||
async def test_stdio_client_sigint_only_process(): # pragma: lax no cover
|
||||
"""Test cleanup with a process that ignores SIGTERM but responds to SIGINT."""
|
||||
# Create a Python script that ignores SIGTERM but handles SIGINT
|
||||
script_content = textwrap.dedent(
|
||||
|
|
@ -481,7 +481,7 @@ class TestChildProcessCleanup:
|
|||
await anyio.sleep(0.5)
|
||||
|
||||
# Verify child is writing
|
||||
if os.path.exists(marker_file): # pragma: no cover
|
||||
if os.path.exists(marker_file): # pragma: no branch
|
||||
size1 = os.path.getsize(marker_file)
|
||||
await anyio.sleep(0.3)
|
||||
size2 = os.path.getsize(marker_file)
|
||||
|
|
|
|||
|
|
@ -34,10 +34,8 @@ def fastmcp_server() -> FastMCP:
|
|||
"""Create a FastMCP server for testing."""
|
||||
server = FastMCP("test")
|
||||
|
||||
# pragma: no cover on handlers below - they exist only to register capabilities.
|
||||
# Transport tests verify stream creation and basic protocol, not handler invocation.
|
||||
@server.tool()
|
||||
def greet(name: str) -> str: # pragma: no cover
|
||||
def greet(name: str) -> str:
|
||||
"""Greet someone by name."""
|
||||
return f"Hello, {name}!"
|
||||
|
||||
|
|
|
|||
|
|
@ -310,8 +310,7 @@ async def test_task_metadata_in_call_tool_request() -> None:
|
|||
async with anyio.create_task_group() as tg:
|
||||
|
||||
async def handle_messages():
|
||||
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
|
||||
async for message in server_session.incoming_messages: # pragma: no cover
|
||||
async for message in server_session.incoming_messages: # pragma: no branch
|
||||
await server._handle_message(message, server_session, {}, False)
|
||||
|
||||
tg.start_soon(handle_messages)
|
||||
|
|
@ -388,9 +387,9 @@ async def test_task_metadata_is_task_property() -> None:
|
|||
),
|
||||
) as server_session:
|
||||
async with anyio.create_task_group() as tg:
|
||||
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
|
||||
async def handle_messages(): # pragma: no cover
|
||||
async for message in server_session.incoming_messages:
|
||||
|
||||
async def handle_messages():
|
||||
async for message in server_session.incoming_messages: # pragma: no branch
|
||||
await server._handle_message(message, server_session, {}, False)
|
||||
|
||||
tg.start_soon(handle_messages)
|
||||
|
|
@ -573,7 +572,7 @@ async def test_build_elicit_form_request() -> None:
|
|||
assert (
|
||||
request_with_task.params["_meta"]["io.modelcontextprotocol/related-task"]["taskId"] == "test-task-123"
|
||||
)
|
||||
finally: # pragma: no cover
|
||||
finally:
|
||||
await server_to_client_send.aclose()
|
||||
await server_to_client_receive.aclose()
|
||||
await client_to_server_send.aclose()
|
||||
|
|
@ -619,7 +618,7 @@ async def test_build_elicit_url_request() -> None:
|
|||
assert (
|
||||
request_with_task.params["_meta"]["io.modelcontextprotocol/related-task"]["taskId"] == "test-task-789"
|
||||
)
|
||||
finally: # pragma: no cover
|
||||
finally:
|
||||
await server_to_client_send.aclose()
|
||||
await server_to_client_receive.aclose()
|
||||
await client_to_server_send.aclose()
|
||||
|
|
@ -670,7 +669,7 @@ async def test_build_create_message_request() -> None:
|
|||
request_with_task.params["_meta"]["io.modelcontextprotocol/related-task"]["taskId"]
|
||||
== "sampling-task-456"
|
||||
)
|
||||
finally: # pragma: no cover
|
||||
finally:
|
||||
await server_to_client_send.aclose()
|
||||
await server_to_client_receive.aclose()
|
||||
await client_to_server_send.aclose()
|
||||
|
|
@ -707,7 +706,7 @@ async def test_send_message() -> None:
|
|||
received = await server_to_client_receive.receive()
|
||||
assert isinstance(received.message, JSONRPCNotification)
|
||||
assert received.message.method == "test/notification"
|
||||
finally: # pragma: no cover
|
||||
finally: # pragma: lax no cover
|
||||
await server_to_client_send.aclose()
|
||||
await server_to_client_receive.aclose()
|
||||
await client_to_server_send.aclose()
|
||||
|
|
@ -761,7 +760,7 @@ async def test_response_routing_success() -> None:
|
|||
assert len(routed_responses) == 1
|
||||
assert routed_responses[0]["id"] == "test-req-1"
|
||||
assert routed_responses[0]["response"]["status"] == "ok"
|
||||
finally: # pragma: no cover
|
||||
finally: # pragma: lax no cover
|
||||
await server_to_client_send.aclose()
|
||||
await server_to_client_receive.aclose()
|
||||
await client_to_server_send.aclose()
|
||||
|
|
@ -816,7 +815,7 @@ async def test_response_routing_error() -> None:
|
|||
assert len(routed_errors) == 1
|
||||
assert routed_errors[0]["id"] == "test-req-2"
|
||||
assert routed_errors[0]["error"].message == "Test error"
|
||||
finally: # pragma: no cover
|
||||
finally: # pragma: lax no cover
|
||||
await server_to_client_send.aclose()
|
||||
await server_to_client_receive.aclose()
|
||||
await client_to_server_send.aclose()
|
||||
|
|
@ -874,7 +873,7 @@ async def test_response_routing_skips_non_matching_routers() -> None:
|
|||
|
||||
# Verify both routers were called (first returned False, second returned True)
|
||||
assert router_calls == ["non_matching_response", "matching_response"]
|
||||
finally: # pragma: no cover
|
||||
finally: # pragma: lax no cover
|
||||
await server_to_client_send.aclose()
|
||||
await server_to_client_receive.aclose()
|
||||
await client_to_server_send.aclose()
|
||||
|
|
@ -933,7 +932,7 @@ async def test_error_routing_skips_non_matching_routers() -> None:
|
|||
|
||||
# Verify both routers were called (first returned False, second returned True)
|
||||
assert router_calls == ["non_matching_error", "matching_error"]
|
||||
finally: # pragma: no cover
|
||||
finally: # pragma: lax no cover
|
||||
await server_to_client_send.aclose()
|
||||
await server_to_client_receive.aclose()
|
||||
await client_to_server_send.aclose()
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ async def test_lifespan_cleanup_executed():
|
|||
|
||||
# Give server a moment to complete cleanup
|
||||
with anyio.move_on_after(5.0):
|
||||
while not Path(cleanup_marker).exists(): # pragma: no cover
|
||||
while not Path(cleanup_marker).exists(): # pragma: lax no cover
|
||||
await anyio.sleep(0.1)
|
||||
|
||||
# Verify cleanup marker was created - this works now that stdio_client
|
||||
|
|
@ -113,9 +113,9 @@ async def test_lifespan_cleanup_executed():
|
|||
finally:
|
||||
# Clean up files
|
||||
for path in [server_script, startup_marker, cleanup_marker]:
|
||||
try: # pragma: no cover
|
||||
try: # pragma: lax no cover
|
||||
Path(path).unlink()
|
||||
except FileNotFoundError: # pragma: no cover
|
||||
except FileNotFoundError: # pragma: lax no cover
|
||||
pass
|
||||
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ async def test_stdin_close_triggers_cleanup():
|
|||
await anyio.sleep(0.1)
|
||||
|
||||
# Check if process is still running
|
||||
if hasattr(process, "returncode") and process.returncode is not None: # pragma: no cover
|
||||
if hasattr(process, "returncode") and process.returncode is not None: # pragma: lax no cover
|
||||
pytest.fail(f"Server process exited with code {process.returncode}")
|
||||
|
||||
assert Path(startup_marker).exists(), "Server startup marker not created"
|
||||
|
|
@ -217,14 +217,14 @@ async def test_stdin_close_triggers_cleanup():
|
|||
try:
|
||||
with anyio.fail_after(5.0): # Increased from 2.0 to 5.0
|
||||
await process.wait()
|
||||
except TimeoutError: # pragma: no cover
|
||||
except TimeoutError: # pragma: lax no cover
|
||||
# If it doesn't exit after stdin close, terminate it
|
||||
process.terminate()
|
||||
await process.wait()
|
||||
|
||||
# Check if cleanup ran
|
||||
with anyio.move_on_after(5.0):
|
||||
while not Path(cleanup_marker).exists(): # pragma: no cover
|
||||
while not Path(cleanup_marker).exists(): # pragma: lax no cover
|
||||
await anyio.sleep(0.1)
|
||||
|
||||
# Verify the cleanup ran - stdin closure enables graceful shutdown
|
||||
|
|
@ -234,7 +234,7 @@ async def test_stdin_close_triggers_cleanup():
|
|||
finally:
|
||||
# Clean up files
|
||||
for path in [server_script, startup_marker, cleanup_marker]:
|
||||
try: # pragma: no cover
|
||||
try: # pragma: lax no cover
|
||||
Path(path).unlink()
|
||||
except FileNotFoundError: # pragma: no cover
|
||||
except FileNotFoundError: # pragma: lax no cover
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -33,10 +33,10 @@ async def test_resource_templates():
|
|||
assert len(templates) == 2
|
||||
|
||||
# Verify template details
|
||||
greeting_template = next(t for t in templates if t.name == "get_greeting") # pragma: no cover
|
||||
greeting_template = next(t for t in templates if t.name == "get_greeting")
|
||||
assert greeting_template.uri_template == "greeting://{name}"
|
||||
assert greeting_template.description == "Get a personalized greeting"
|
||||
|
||||
profile_template = next(t for t in templates if t.name == "get_user_profile") # pragma: no cover
|
||||
profile_template = next(t for t in templates if t.name == "get_user_profile")
|
||||
assert profile_template.uri_template == "users://{user_id}/profile"
|
||||
assert profile_template.description == "Dynamic user data"
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ def check_logs_for_race_condition_errors(caplog: pytest.LogCaptureFixture, test_
|
|||
# Check for specific race condition errors in logs
|
||||
errors_found: list[str] = []
|
||||
|
||||
for record in caplog.records: # pragma: no cover
|
||||
for record in caplog.records: # pragma: lax no cover
|
||||
message = record.getMessage()
|
||||
if "ClosedResourceError" in message:
|
||||
errors_found.append("ClosedResourceError")
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ async def test_notification_validation_error(tmp_path: Path):
|
|||
# proving server is still responsive
|
||||
result = await session.call_tool("fast", read_timeout_seconds=None)
|
||||
assert result.content == [TextContent(type="text", text="fast 3")]
|
||||
scope.cancel() # pragma: no cover
|
||||
scope.cancel() # pragma: lax no cover
|
||||
|
||||
# Run server and client in separate task groups to avoid cancellation
|
||||
server_writer, server_reader = anyio.create_memory_object_stream[SessionMessage](1)
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ async def test_malformed_initialize_request_does_not_crash_server():
|
|||
|
||||
except anyio.WouldBlock: # pragma: no cover
|
||||
pytest.fail("No response received - server likely crashed")
|
||||
finally: # pragma: no cover
|
||||
finally: # pragma: lax no cover
|
||||
# Close all streams to ensure proper cleanup
|
||||
await read_send_stream.aclose()
|
||||
await write_send_stream.aclose()
|
||||
|
|
@ -143,7 +143,7 @@ async def test_multiple_concurrent_malformed_requests():
|
|||
assert isinstance(response, JSONRPCError)
|
||||
assert response.id == f"malformed_{i}"
|
||||
assert response.error.code == INVALID_PARAMS
|
||||
finally: # pragma: no cover
|
||||
finally: # pragma: lax no cover
|
||||
# Close all streams to ensure proper cleanup
|
||||
await read_send_stream.aclose()
|
||||
await write_send_stream.aclose()
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ class MockOAuthProvider(OAuthAuthorizationServerProvider[AuthorizationCode, Refr
|
|||
|
||||
async def revoke_token(self, token: AccessToken | RefreshToken) -> None:
|
||||
match token:
|
||||
case RefreshToken(): # pragma: no cover
|
||||
case RefreshToken(): # pragma: lax no cover
|
||||
# Remove the refresh token
|
||||
del self.refresh_tokens[token.token]
|
||||
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ def temp_file():
|
|||
f.write(content)
|
||||
path = Path(f.name).resolve()
|
||||
yield path
|
||||
try: # pragma: no cover
|
||||
try: # pragma: lax no cover
|
||||
path.unlink()
|
||||
except FileNotFoundError: # pragma: no cover
|
||||
except FileNotFoundError: # pragma: lax no cover
|
||||
pass # File was already deleted by the test
|
||||
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ class TestFileResource:
|
|||
|
||||
@pytest.mark.skipif(os.name == "nt", reason="File permissions behave differently on Windows")
|
||||
@pytest.mark.anyio
|
||||
async def test_permission_error(self, temp_file: Path): # pragma: no cover
|
||||
async def test_permission_error(self, temp_file: Path): # pragma: lax no cover
|
||||
"""Test reading a file without permissions."""
|
||||
temp_file.chmod(0o000) # Remove all permissions
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ def temp_file():
|
|||
f.write(content)
|
||||
path = Path(f.name).resolve()
|
||||
yield path
|
||||
try: # pragma: no cover
|
||||
try: # pragma: lax no cover
|
||||
path.unlink()
|
||||
except FileNotFoundError: # pragma: no cover
|
||||
except FileNotFoundError: # pragma: lax no cover
|
||||
pass # File was already deleted by the test
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class TestResourceTemplate:
|
|||
def test_template_creation(self):
|
||||
"""Test creating a template from a function."""
|
||||
|
||||
def my_func(key: str, value: int) -> dict[str, Any]: # pragma: no cover
|
||||
def my_func(key: str, value: int) -> dict[str, Any]:
|
||||
return {"key": key, "value": value}
|
||||
|
||||
template = ResourceTemplate.from_function(
|
||||
|
|
@ -239,7 +239,7 @@ class TestResourceTemplateAnnotations:
|
|||
async def test_template_created_resources_inherit_annotations(self):
|
||||
"""Test that resources created from templates inherit annotations."""
|
||||
|
||||
def get_item(item_id: str) -> str: # pragma: no cover
|
||||
def get_item(item_id: str) -> str:
|
||||
return f"Item {item_id}"
|
||||
|
||||
annotations = Annotations(priority=0.6)
|
||||
|
|
|
|||
|
|
@ -65,12 +65,10 @@ async def test_stdio_elicitation():
|
|||
create_ask_user_tool(mcp)
|
||||
|
||||
# Create a custom handler for elicitation requests
|
||||
async def elicitation_callback(
|
||||
context: RequestContext[ClientSession, None], params: ElicitRequestParams
|
||||
): # pragma: no cover
|
||||
async def elicitation_callback(context: RequestContext[ClientSession, None], params: ElicitRequestParams):
|
||||
if params.message == "Tool wants to ask: What is your name?":
|
||||
return ElicitResult(action="accept", content={"answer": "Test User"})
|
||||
else:
|
||||
else: # pragma: no cover
|
||||
raise ValueError(f"Unexpected elicitation message: {params.message}")
|
||||
|
||||
await call_tool_and_assert(
|
||||
|
|
@ -99,10 +97,10 @@ async def test_elicitation_schema_validation():
|
|||
|
||||
def create_validation_tool(name: str, schema_class: type[BaseModel]):
|
||||
@mcp.tool(name=name, description=f"Tool testing {name}")
|
||||
async def tool(ctx: Context[ServerSession, None]) -> str: # pragma: no cover
|
||||
async def tool(ctx: Context[ServerSession, None]) -> str:
|
||||
try:
|
||||
await ctx.elicit(message="This should fail validation", schema=schema_class)
|
||||
return "Should not reach here"
|
||||
return "Should not reach here" # pragma: no cover
|
||||
except TypeError as e:
|
||||
return f"Validation failed as expected: {str(e)}"
|
||||
|
||||
|
|
@ -190,10 +188,10 @@ async def test_elicitation_with_optional_fields():
|
|||
optional_list: list[int] | None = Field(default=None, description="Invalid optional list")
|
||||
|
||||
@mcp.tool(description="Tool with invalid optional field")
|
||||
async def invalid_optional_tool(ctx: Context[ServerSession, None]) -> str: # pragma: no cover
|
||||
async def invalid_optional_tool(ctx: Context[ServerSession, None]) -> str:
|
||||
try:
|
||||
await ctx.elicit(message="This should fail", schema=InvalidOptionalSchema)
|
||||
return "Should not reach here"
|
||||
return "Should not reach here" # pragma: no cover
|
||||
except TypeError as e:
|
||||
return f"Validation failed: {str(e)}"
|
||||
|
||||
|
|
|
|||
|
|
@ -516,7 +516,7 @@ async def test_str_annotation_runtime_validation():
|
|||
containing valid JSON to ensure they are passed as strings, not parsed objects.
|
||||
"""
|
||||
|
||||
def handle_json_payload(payload: str, strict_mode: bool = False) -> str: # pragma: no cover
|
||||
def handle_json_payload(payload: str, strict_mode: bool = False) -> str:
|
||||
"""Function that processes a JSON payload as a string."""
|
||||
# This function expects to receive the raw JSON string
|
||||
# It might parse it later after validation or logging
|
||||
|
|
@ -833,7 +833,7 @@ def test_unstructured_output_unannotated_class():
|
|||
|
||||
|
||||
def test_tool_call_result_is_unstructured_and_not_converted():
|
||||
def func_returning_call_tool_result() -> CallToolResult: # pragma: no cover
|
||||
def func_returning_call_tool_result() -> CallToolResult:
|
||||
return CallToolResult(content=[])
|
||||
|
||||
meta = func_metadata(func_returning_call_tool_result)
|
||||
|
|
@ -846,7 +846,7 @@ def test_tool_call_result_annotated_is_structured_and_converted():
|
|||
class PersonClass(BaseModel):
|
||||
name: str
|
||||
|
||||
def func_returning_annotated_tool_call_result() -> Annotated[CallToolResult, PersonClass]: # pragma: no cover
|
||||
def func_returning_annotated_tool_call_result() -> Annotated[CallToolResult, PersonClass]:
|
||||
return CallToolResult(content=[], structured_content={"name": "Brandon"})
|
||||
|
||||
meta = func_metadata(func_returning_annotated_tool_call_result)
|
||||
|
|
@ -866,7 +866,7 @@ def test_tool_call_result_annotated_is_structured_and_invalid():
|
|||
class PersonClass(BaseModel):
|
||||
name: str
|
||||
|
||||
def func_returning_annotated_tool_call_result() -> Annotated[CallToolResult, PersonClass]: # pragma: no cover
|
||||
def func_returning_annotated_tool_call_result() -> Annotated[CallToolResult, PersonClass]:
|
||||
return CallToolResult(content=[], structured_content={"person": "Brandon"})
|
||||
|
||||
meta = func_metadata(func_returning_annotated_tool_call_result)
|
||||
|
|
@ -1092,7 +1092,7 @@ def test_basemodel_reserved_names():
|
|||
async def test_basemodel_reserved_names_validation():
|
||||
"""Test that validation and calling works with reserved parameter names"""
|
||||
|
||||
def func_with_reserved_names( # pragma: no cover
|
||||
def func_with_reserved_names(
|
||||
model_dump: str,
|
||||
model_validate: int,
|
||||
dict: list[str],
|
||||
|
|
|
|||
|
|
@ -887,7 +887,7 @@ class TestServerResourceTemplates:
|
|||
def get_data_mismatched(org: str, repo_2: str) -> str: # pragma: no cover
|
||||
return f"Data for {org}"
|
||||
|
||||
"""Test that a resource with no parameters works as a regular resource""" # pragma: no cover
|
||||
"""Test that a resource with no parameters works as a regular resource"""
|
||||
mcp = FastMCP()
|
||||
|
||||
@mcp.resource("resource://static")
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ class TestAddTools:
|
|||
class TestCallTools:
|
||||
@pytest.mark.anyio
|
||||
async def test_call_tool(self):
|
||||
def sum(a: int, b: int) -> int: # pragma: no cover
|
||||
def sum(a: int, b: int) -> int:
|
||||
"""Add two numbers."""
|
||||
return a + b
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ class TestCallTools:
|
|||
|
||||
@pytest.mark.anyio
|
||||
async def test_call_async_tool(self):
|
||||
async def double(n: int) -> int: # pragma: no cover
|
||||
async def double(n: int) -> int:
|
||||
"""Double a number."""
|
||||
return n * 2
|
||||
|
||||
|
|
@ -260,7 +260,7 @@ class TestCallTools:
|
|||
|
||||
@pytest.mark.anyio
|
||||
async def test_call_tool_with_list_int_input(self):
|
||||
def sum_vals(vals: list[int]) -> int: # pragma: no cover
|
||||
def sum_vals(vals: list[int]) -> int:
|
||||
return sum(vals)
|
||||
|
||||
manager = ToolManager()
|
||||
|
|
@ -273,7 +273,7 @@ class TestCallTools:
|
|||
|
||||
@pytest.mark.anyio
|
||||
async def test_call_tool_with_list_str_or_str_input(self):
|
||||
def concat_strs(vals: list[str] | str) -> str: # pragma: no cover
|
||||
def concat_strs(vals: list[str] | str) -> str:
|
||||
return vals if isinstance(vals, str) else "".join(vals)
|
||||
|
||||
manager = ToolManager()
|
||||
|
|
@ -297,7 +297,7 @@ class TestCallTools:
|
|||
shrimp: list[Shrimp]
|
||||
x: None
|
||||
|
||||
def name_shrimp(tank: MyShrimpTank, ctx: Context[ServerSessionT, None]) -> list[str]: # pragma: no cover
|
||||
def name_shrimp(tank: MyShrimpTank, ctx: Context[ServerSessionT, None]) -> list[str]:
|
||||
return [x.name for x in tank.shrimp]
|
||||
|
||||
manager = ToolManager()
|
||||
|
|
@ -375,7 +375,7 @@ class TestContextHandling:
|
|||
async def test_context_injection_async(self):
|
||||
"""Test that context is properly injected in async tools."""
|
||||
|
||||
async def async_tool(x: int, ctx: Context[ServerSessionT, None]) -> str: # pragma: no cover
|
||||
async def async_tool(x: int, ctx: Context[ServerSessionT, None]) -> str:
|
||||
assert isinstance(ctx, Context)
|
||||
return str(x)
|
||||
|
||||
|
|
@ -467,7 +467,7 @@ class TestStructuredOutput:
|
|||
name: str
|
||||
age: int
|
||||
|
||||
def get_user(user_id: int) -> UserOutput: # pragma: no cover
|
||||
def get_user(user_id: int) -> UserOutput:
|
||||
"""Get user by ID."""
|
||||
return UserOutput(name="John", age=30)
|
||||
|
||||
|
|
@ -481,7 +481,7 @@ class TestStructuredOutput:
|
|||
async def test_tool_with_primitive_output(self):
|
||||
"""Test tool with primitive return type."""
|
||||
|
||||
def double_number(n: int) -> int: # pragma: no cover
|
||||
def double_number(n: int) -> int:
|
||||
"""Double a number."""
|
||||
return 10
|
||||
|
||||
|
|
@ -502,7 +502,7 @@ class TestStructuredOutput:
|
|||
|
||||
expected_output = {"name": "Alice", "age": 25}
|
||||
|
||||
def get_user_dict(user_id: int) -> UserDict: # pragma: no cover
|
||||
def get_user_dict(user_id: int) -> UserDict:
|
||||
"""Get user as dict."""
|
||||
return UserDict(name="Alice", age=25)
|
||||
|
||||
|
|
@ -522,7 +522,7 @@ class TestStructuredOutput:
|
|||
|
||||
expected_output = {"name": "Bob", "age": 40}
|
||||
|
||||
def get_person() -> Person: # pragma: no cover
|
||||
def get_person() -> Person:
|
||||
"""Get a person."""
|
||||
return Person("Bob", 40)
|
||||
|
||||
|
|
@ -539,7 +539,7 @@ class TestStructuredOutput:
|
|||
expected_list = [1, 2, 3, 4, 5]
|
||||
expected_output = {"result": expected_list}
|
||||
|
||||
def get_numbers() -> list[int]: # pragma: no cover
|
||||
def get_numbers() -> list[int]:
|
||||
"""Get a list of numbers."""
|
||||
return expected_list
|
||||
|
||||
|
|
@ -590,7 +590,7 @@ class TestStructuredOutput:
|
|||
async def test_tool_with_dict_str_any_output(self):
|
||||
"""Test tool with dict[str, Any] return type."""
|
||||
|
||||
def get_config() -> dict[str, Any]: # pragma: no cover
|
||||
def get_config() -> dict[str, Any]:
|
||||
"""Get configuration"""
|
||||
return {"debug": True, "port": 8080, "features": ["auth", "logging"]}
|
||||
|
||||
|
|
@ -615,7 +615,7 @@ class TestStructuredOutput:
|
|||
async def test_tool_with_dict_str_typed_output(self):
|
||||
"""Test tool with dict[str, T] return type for specific T."""
|
||||
|
||||
def get_scores() -> dict[str, int]: # pragma: no cover
|
||||
def get_scores() -> dict[str, int]:
|
||||
"""Get player scores"""
|
||||
return {"alice": 100, "bob": 85, "charlie": 92}
|
||||
|
||||
|
|
@ -879,7 +879,7 @@ class TestRemoveTools:
|
|||
async def test_call_removed_tool_raises_error(self):
|
||||
"""Test that calling a removed tool raises ToolError."""
|
||||
|
||||
def greet(name: str) -> str: # pragma: no cover
|
||||
def greet(name: str) -> str:
|
||||
"""Greet someone."""
|
||||
return f"Hello, {name}!"
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue