refactor: reorganize message handling for better type safety and clarity#239
refactor: reorganize message handling for better type safety and clarity#239dsp-ant merged 9 commits intomainmodelcontextprotocol/python-sdk:mainfrom davidsp/raw-requestmodelcontextprotocol/python-sdk:davidsp/raw-requestCopy head branch name to clipboard
Conversation
2e3388b to
0d651d5
Compare
bhosmer-ant
left a comment
There was a problem hiding this comment.
Couple minor observations inline but LGTM!
| RawT = TypeVar("RawT") | ||
|
|
||
|
|
||
| class MessageFrame(BaseModel, Generic[RawT]): |
There was a problem hiding this comment.
Don't know how fastidious we are about this in general, but fwiw the other classes here are docstringed up pretty thoroughly (and the point of raw in particular might be worth noting here)
Move memory stream type definitions to models.py and use them throughout the codebase for better type safety and maintainability. GitHub-Issue:#201
Updates test files to work with the ParsedMessage stream type aliases and fixes a line length issue in test_201_client_hangs_on_logging.py. Github-Issue:#201
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
…ation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Modified the websocket client to work with the new MessageFrame type, preserving raw message text and properly extracting the root JSON-RPC message when sending. Github-Issue:#204
🤖 Generated with [Claude Code](https://claude.ai/code)
1d57efa to
1c53fc2
Compare
|
This broke a lot types 😢 |
| ReadStream = MemoryObjectReceiveStream[MessageFrame | Exception] | ||
| ReadStreamWriter = MemoryObjectSendStream[MessageFrame | Exception] | ||
| WriteStream = MemoryObjectSendStream[MessageFrame] | ||
| WriteStreamReader = MemoryObjectReceiveStream[MessageFrame] |
There was a problem hiding this comment.
You can't do this if MessageFrame is a generic. It means that all those new types have unkown parameters to the generic type.
| def model_dump(self, *args, **kwargs): | ||
| """ | ||
| Dumps the model to a dictionary, delegating to the root JSONRPCMessage. | ||
| This method allows for consistent serialization of the parsed message. | ||
| """ | ||
| return self.message.model_dump(*args, **kwargs) | ||
|
|
||
| def model_dump_json(self, *args, **kwargs): | ||
| """ | ||
| Dumps the model to a JSON string, delegating to the root JSONRPCMessage. | ||
| This method provides a convenient way to serialize the parsed message to JSON. | ||
| """ | ||
| return self.message.model_dump_json(*args, **kwargs) |
There was a problem hiding this comment.
This is not type safe. You are hiding the parameters with args and kwargs.
|
What's this |
| read_stream: MemoryObjectReceiveStream[types.JSONRPCMessage | Exception], | ||
| write_stream: MemoryObjectSendStream[types.JSONRPCMessage], | ||
| read_stream: ReadStream, | ||
| write_stream: WriteStream, |
There was a problem hiding this comment.
This is not really the end type, since ReadStream and WriteStream are generics, something is missing here.
I believe it's easier to understand the code if we don't hide that those streams are anyio objects. Makes it easier to go around the code.
Summary
Test plan
GitHub-Issue:#201