ci: add strict-no-cover to detect unnecessary coverage pragmas (#1897)
This commit is contained in:
parent
3cfdea0e97
commit
a7ddfdae07
1 changed files with 355 additions and 358 deletions
|
|
@ -222,7 +222,7 @@ class StreamableHTTPServerTransport:
|
|||
"""
|
||||
self.close_sse_stream(GET_STREAM_KEY)
|
||||
|
||||
def _create_session_message( # pragma: no cover
|
||||
def _create_session_message(
|
||||
self,
|
||||
message: JSONRPCMessage,
|
||||
request: Request,
|
||||
|
|
@ -238,10 +238,10 @@ class StreamableHTTPServerTransport:
|
|||
# Only provide close callbacks when client supports resumability
|
||||
if self._event_store and protocol_version >= "2025-11-25":
|
||||
|
||||
async def close_stream_callback() -> None:
|
||||
async def close_stream_callback() -> None: # pragma: no cover
|
||||
self.close_sse_stream(request_id)
|
||||
|
||||
async def close_standalone_stream_callback() -> None:
|
||||
async def close_standalone_stream_callback() -> None: # pragma: no cover
|
||||
self.close_standalone_sse_stream()
|
||||
|
||||
metadata = ServerMessageMetadata(
|
||||
|
|
@ -308,7 +308,7 @@ class StreamableHTTPServerTransport:
|
|||
headers=response_headers,
|
||||
)
|
||||
|
||||
def _create_json_response( # pragma: no cover
|
||||
def _create_json_response(
|
||||
self,
|
||||
response_message: JSONRPCMessage | None,
|
||||
status_code: HTTPStatus = HTTPStatus.OK,
|
||||
|
|
@ -316,10 +316,10 @@ class StreamableHTTPServerTransport:
|
|||
) -> Response:
|
||||
"""Create a JSON response from a JSONRPCMessage"""
|
||||
response_headers = {"Content-Type": CONTENT_TYPE_JSON}
|
||||
if headers:
|
||||
if headers: # pragma: lax no cover
|
||||
response_headers.update(headers)
|
||||
|
||||
if self.mcp_session_id:
|
||||
if self.mcp_session_id: # pragma: lax no cover
|
||||
response_headers[MCP_SESSION_ID_HEADER] = self.mcp_session_id
|
||||
|
||||
return Response(
|
||||
|
|
@ -345,14 +345,14 @@ class StreamableHTTPServerTransport:
|
|||
|
||||
return event_data
|
||||
|
||||
async def _clean_up_memory_streams(self, request_id: RequestId) -> None: # pragma: no cover
|
||||
async def _clean_up_memory_streams(self, request_id: RequestId) -> None:
|
||||
"""Clean up memory streams for a given request ID."""
|
||||
if request_id in self._request_streams:
|
||||
if request_id in self._request_streams: # pragma: no branch
|
||||
try:
|
||||
# Close the request stream
|
||||
await self._request_streams[request_id][0].aclose()
|
||||
await self._request_streams[request_id][1].aclose()
|
||||
except Exception:
|
||||
except Exception: # pragma: no cover
|
||||
# During cleanup, we catch all exceptions since streams might be in various states
|
||||
logger.debug("Error closing memory streams - may already be closed")
|
||||
finally:
|
||||
|
|
@ -366,7 +366,7 @@ class StreamableHTTPServerTransport:
|
|||
# Validate request headers for DNS rebinding protection
|
||||
is_post = request.method == "POST"
|
||||
error_response = await self._security.validate_request(request, is_post=is_post)
|
||||
if error_response: # pragma: no cover
|
||||
if error_response:
|
||||
await error_response(scope, receive, send)
|
||||
return
|
||||
|
||||
|
|
@ -405,12 +405,12 @@ class StreamableHTTPServerTransport:
|
|||
|
||||
return any(part == CONTENT_TYPE_JSON for part in content_type_parts)
|
||||
|
||||
async def _validate_accept_header(self, request: Request, scope: Scope, send: Send) -> bool: # pragma: no cover
|
||||
async def _validate_accept_header(self, request: Request, scope: Scope, send: Send) -> bool:
|
||||
"""Validate Accept header based on response mode. Returns True if valid."""
|
||||
has_json, has_sse = self._check_accept_headers(request)
|
||||
if self.is_json_response_enabled:
|
||||
# For JSON-only responses, only require application/json
|
||||
if not has_json:
|
||||
if not has_json: # pragma: lax no cover
|
||||
response = self._create_error_response(
|
||||
"Not Acceptable: Client must accept application/json",
|
||||
HTTPStatus.NOT_ACCEPTABLE,
|
||||
|
|
@ -456,7 +456,7 @@ class StreamableHTTPServerTransport:
|
|||
await response(scope, receive, send)
|
||||
return
|
||||
|
||||
try: # pragma: no cover
|
||||
try:
|
||||
message = jsonrpc_message_adapter.validate_python(raw_message, by_name=False)
|
||||
except ValidationError as e: # pragma: no cover
|
||||
response = self._create_error_response(
|
||||
|
|
@ -513,12 +513,12 @@ class StreamableHTTPServerTransport:
|
|||
)
|
||||
|
||||
# Extract the request ID outside the try block for proper scope
|
||||
request_id = str(message.id) # pragma: no cover
|
||||
request_id = str(message.id)
|
||||
# Register this stream for the request ID
|
||||
self._request_streams[request_id] = anyio.create_memory_object_stream[EventMessage](0) # pragma: no cover
|
||||
request_stream_reader = self._request_streams[request_id][1] # pragma: no cover
|
||||
self._request_streams[request_id] = anyio.create_memory_object_stream[EventMessage](0)
|
||||
request_stream_reader = self._request_streams[request_id][1]
|
||||
|
||||
if self.is_json_response_enabled: # pragma: no cover
|
||||
if self.is_json_response_enabled:
|
||||
# Process the message
|
||||
metadata = ServerMessageMetadata(request_context=request)
|
||||
session_message = SessionMessage(message, metadata=metadata)
|
||||
|
|
@ -529,13 +529,13 @@ class StreamableHTTPServerTransport:
|
|||
response_message = None
|
||||
|
||||
# Use similar approach to SSE writer for consistency
|
||||
async for event_message in request_stream_reader:
|
||||
async for event_message in request_stream_reader: # pragma: no branch
|
||||
# If it's a response, this is what we're waiting for
|
||||
if isinstance(event_message.message, JSONRPCResponse | JSONRPCError):
|
||||
response_message = event_message.message
|
||||
break
|
||||
# For notifications and request, keep waiting
|
||||
else:
|
||||
else: # pragma: no cover
|
||||
logger.debug(f"received: {event_message.message.method}")
|
||||
|
||||
# At this point we should have a response
|
||||
|
|
@ -543,7 +543,7 @@ class StreamableHTTPServerTransport:
|
|||
# Create JSON response
|
||||
response = self._create_json_response(response_message)
|
||||
await response(scope, receive, send)
|
||||
else:
|
||||
else: # pragma: no cover
|
||||
# This shouldn't happen in normal operation
|
||||
logger.error("No response message received before stream closed")
|
||||
response = self._create_error_response(
|
||||
|
|
@ -551,7 +551,7 @@ class StreamableHTTPServerTransport:
|
|||
HTTPStatus.INTERNAL_SERVER_ERROR,
|
||||
)
|
||||
await response(scope, receive, send)
|
||||
except Exception:
|
||||
except Exception: # pragma: no cover
|
||||
logger.exception("Error processing JSON response")
|
||||
response = self._create_error_response(
|
||||
"Error processing request",
|
||||
|
|
@ -762,7 +762,7 @@ class StreamableHTTPServerTransport:
|
|||
request_stream_keys = list(self._request_streams.keys())
|
||||
|
||||
# Close all request streams asynchronously
|
||||
for key in request_stream_keys: # pragma: no cover
|
||||
for key in request_stream_keys: # pragma: lax no cover
|
||||
await self._clean_up_memory_streams(key)
|
||||
|
||||
# Clear the request streams dictionary immediately
|
||||
|
|
@ -967,9 +967,9 @@ class StreamableHTTPServerTransport:
|
|||
# Start a task group for message routing
|
||||
async with anyio.create_task_group() as tg:
|
||||
# Create a message router that distributes messages to request streams
|
||||
async def message_router(): # pragma: no cover
|
||||
async def message_router():
|
||||
try:
|
||||
async for session_message in write_stream_reader:
|
||||
async for session_message in write_stream_reader: # pragma: no branch
|
||||
# Determine which request stream(s) should receive this message
|
||||
message = session_message.message
|
||||
target_request_id = None
|
||||
|
|
@ -980,7 +980,7 @@ class StreamableHTTPServerTransport:
|
|||
# send it there
|
||||
target_request_id = response_id
|
||||
# Extract related_request_id from meta if it exists
|
||||
elif (
|
||||
elif ( # pragma: no cover
|
||||
session_message.metadata is not None
|
||||
and isinstance(
|
||||
session_message.metadata,
|
||||
|
|
@ -996,7 +996,7 @@ class StreamableHTTPServerTransport:
|
|||
# regardless of whether a client is connected
|
||||
# messages will be replayed on the re-connect
|
||||
event_id = None
|
||||
if self._event_store:
|
||||
if self._event_store: # pragma: lax no cover
|
||||
event_id = await self._event_store.store_event(request_stream_id, message)
|
||||
logger.debug(f"Stored {event_id} from {request_stream_id}")
|
||||
|
||||
|
|
@ -1004,13 +1004,13 @@ class StreamableHTTPServerTransport:
|
|||
try:
|
||||
# Send both the message and the event ID
|
||||
await self._request_streams[request_stream_id][0].send(EventMessage(message, event_id))
|
||||
except (
|
||||
except ( # pragma: no cover
|
||||
anyio.BrokenResourceError,
|
||||
anyio.ClosedResourceError,
|
||||
):
|
||||
# Stream might be closed, remove from registry
|
||||
self._request_streams.pop(request_stream_id, None)
|
||||
else:
|
||||
else: # pragma: no cover
|
||||
logger.debug(
|
||||
f"""Request stream {request_stream_id} not found
|
||||
for message. Still processing message as the client
|
||||
|
|
@ -1021,7 +1021,7 @@ class StreamableHTTPServerTransport:
|
|||
logger.debug("Read stream closed by client")
|
||||
else:
|
||||
logger.exception("Unexpected closure of read stream in message router")
|
||||
except Exception:
|
||||
except Exception: # pragma: lax no cover
|
||||
logger.exception("Error in message router")
|
||||
|
||||
# Start the message router
|
||||
|
|
@ -1031,7 +1031,7 @@ class StreamableHTTPServerTransport:
|
|||
# Yield the streams for the caller to use
|
||||
yield read_stream, write_stream
|
||||
finally:
|
||||
for stream_id in list(self._request_streams.keys()): # pragma: no cover
|
||||
for stream_id in list(self._request_streams.keys()): # pragma: lax no cover
|
||||
await self._clean_up_memory_streams(stream_id)
|
||||
self._request_streams.clear()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue