Skip to content
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

Incompatible types in assignment (x: SomeMessage = Message) #97

Open
DaniGuardiola opened this issue Oct 10, 2019 · 3 comments

Comments

@DaniGuardiola
Copy link

@DaniGuardiola DaniGuardiola commented Oct 10, 2019

I have the following code:

from proto.example_pb2 import SomeMessage
from google.protobuf.message import Message


def request(...) -> Message:
	...

result: SomeMessage = request(
    ...
)

Request will return a protobuf message which can vary depending on the input parameters. This is giving the following mypy error:

error: Incompatible types in assignment (expression has type "Message", variable has type "SomeMessage")

Now, I understand why this is happening: Message is not assignable to SomeMessage. It would be valid the other way around (SomeMessage -> Message) because SomeMessage is a subclass of Message.

The reasoning behind this code is that while request can return any message, when I use it I already know which specific message it will return, and I want to be able to type it like this. I just don't know how to go about it.

The only solution I thought about is to use @overload with some Literal types to set the return of every message type, as it really only depends on the value a string parameter, but it seems a bit overkill. I have some other situations in my code where this happens (even without protobuf) so what I'm really asking is for help on what pattern I should be using in these kind of situations, because I'm all out of ideas.

Can anyone help me figure this out?

Thanks :)

@nipunn1313

This comment has been minimized.

Copy link
Contributor

@nipunn1313 nipunn1313 commented Oct 10, 2019

There exists a cast method in the typing module which might allow you to force a conversion like this.

Generally speaking, a single method that could return a variety of types based on the input - is not a strongly typed method - so you will have to cast. The input string is “stringly typed” encoding the type in a way that bypasses the type system.

One pattern might be to have N typed methods (either with overload like you mention - or even N methods with different names that don’t require arguments).

@nipunn1313

This comment has been minimized.

Copy link
Contributor

@nipunn1313 nipunn1313 commented Oct 10, 2019

You may be able to ask a similar question in the mypy repo to get more eyes on it for possible alternatives.

@ikonst

This comment has been minimized.

Copy link

@ikonst ikonst commented Oct 11, 2019

If you know which message each kind of request returns, this sounds very much like RPC services. In such case, I would expect your RPC service (defined in Protobuf) to result in a generated Python typestub to the effect of:

class MyService:
   def foo(my_request: MyRequest) -> MyResult: ...
   def bar(...) -> ...: ...

etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.