-
Notifications
You must be signed in to change notification settings - Fork 642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DOC: Generic zmq.Context is unclear #1966
Comments
Yeah, type-wise I don't know the best way to handle the fact that the base classes are indeed base classes and have a default implementation, but I believe the annotation that only accepts the default implementation is context: zmq.Context[zmq.Socket[bytes]] This will accept Liskov substitution makes the false assumption that subclasses are subtypes, which isn't a valid assumption. |
I'm not sure of the historicity of this but: isn't the LSP making an assertion about how things should be done rather than making an assumption about how they are done? |
I think python/typing#241 makes a point that is a middle ground (and/or is just the point you were getting at) that we use subclassing to provide default implementations of things without intending it to indicate subtyping. And I've just read to the bottom of that issue and seen that you've made this exact point there. Could it not be argued that the current implementation has the same problem as the "Has a" implementation in that you've had to provide type overrides for a bunch of methods on |
The issue with this solution is that my plan was to just throw a |
I think you can catch errors with your previous code if you enable stricter type checking. Using the generic
Also because they are generics, the return type of the socket methods will all be For example: from dataclasses import dataclass
import zmq
import zmq.asyncio
@dataclass
class ServerManager:
generic_context: zmq.Context
sync_context: zmq.Context[zmq.Socket[bytes]]
async_context: zmq.asyncio.Context
def recv(self) -> bytes:
sock = self.generic_context.socket(zmq.PUSH)
reveal_type(sock.recv()) # Any
sock2 = self.sync_context.socket(zmq.PUSH)
reveal_type(sock2.recv()) # bytes
sock3 = self.async_context.socket(zmq.PUSH)
reveal_type(sock3.recv()) # Awaitable[Union[builtins.bytes, zmq.sugar.frame.Frame] |
I see what you mean. I got distracted by talking about LSP and failed to take on board that you said they were generics. |
Do you think there's anything left to do here? |
It might be useful to have a little more documentation on the type annotations we should use, though I may just have missed it. Potentially I think it may be more immediately obvious how to use the types if you had, say, a base class and then a synchronous subclass and an asynchronous subclass so they wouldn't typecheck as each other. (specifically I think this may be advantageous because in my experience python devs aren't used to using generics outside of collections -- though with recent improvements to the ability to express generics this may change). I certainly wouldn't complain if you just closed the issue as wontfix; there is a functional solution to the problem, it's just not what I expected. |
Docs are a good point. I'm not particularly inclined to change code to suit typing tools when there's no actual problem with the code itself, just in the typing tools ability to describe it. I can't think of a way that wouldn't break things, and not breaking things is the single most important thing in pyzmq right now. |
#1970 adds a note in the docs and SyncContext / SyncSocket TypeAliases for convenience |
This is a pyzmq bug
What pyzmq version?
25.1.2
What libzmq version?
4.3.4
Python version (and how it was installed)
3.10.12 from deadsnakes ppa
OS
Ubuntu 22.04.4
What happened?
In the process of switching an existing zmq codebase over to use
zmq.asyncio
I would expect a type error to be thrown anywhere that I have tried to provide azmq.asyncio.Context
orzmq.asyncio.Socket
where I have annotated something as azmq.Context
orzmq.Socket
but becausezmq.asyncio.{Context,Socket}
subclasseszmq.{Context,Socket}
it is considered a valid type.Code to reproduce bug
Traceback, if applicable
No response
More info
No response
The text was updated successfully, but these errors were encountered: