-
Notifications
You must be signed in to change notification settings - Fork 80
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
Function is not valid as a type #108
Comments
Interesting. Thanks for the report. Do you know what line of your source file you see this error at? What is going on in your source leading to this? Is it at the time of import? The These errors:
seem to indicate that something in your code is using Foo as a function rather than as a message? If you have a repro of the situation that you are willing to share, that'll help (ideally minimal). Hopefully this is enough information to help your debugging! |
I believe I've tracked down the issue. It appears there are two different errors that arise as a result of the same underlying problem — when an instance member/method has the same name as an existing type. Here is one way to trigger an error by using an enum AThing {
Unknown = 0;
A = 1;
B = 2;
}
message Foo {
AThing AThing = 1;
} This results in the following generated # definition of AThing
# ...
class Foo(google___protobuf___message___Message):
DESCRIPTOR: google___protobuf___descriptor___Descriptor = ...
AThing = ... # type: AThing
def __init__(self,
*,
AThing : typing___Optional[AThing] = None,
) -> None: ...
if sys.version_info >= (3,):
@classmethod
def FromString(cls, s: builtin___bytes) -> Foo: ...
else:
@classmethod
def FromString(cls, s: typing___Union[builtin___bytes, builtin___buffer, builtin___unicode]) -> Foo: ...
def MergeFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
def CopyFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
if sys.version_info >= (3,):
def ClearField(self, field_name: typing_extensions___Literal[u"AThing"]) -> None: ...
else:
def ClearField(self, field_name: typing_extensions___Literal[u"AThing",b"AThing"]) -> None: ... And attempts to use from foo_pb2 import AThing, Foo
x: Foo = Foo(AThing=AThing.A)
Per python/mypy#1775, this can be fixed by adding an alias for # definition of AThing
# ...
_AThing = AThing
class Foo(google___protobuf___message___Message):
DESCRIPTOR: google___protobuf___descriptor___Descriptor = ...
AThing = ... # type: _AThing
def __init__(self,
*,
AThing : typing___Optional[_AThing] = None,
) -> None: ...
if sys.version_info >= (3,):
@classmethod
def FromString(cls, s: builtin___bytes) -> Foo: ...
else:
@classmethod
def FromString(cls, s: typing___Union[builtin___bytes, builtin___buffer, builtin___unicode]) -> Foo: ...
def MergeFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
def CopyFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
if sys.version_info >= (3,):
def ClearField(self, field_name: typing_extensions___Literal[u"AThing"]) -> None: ...
else:
def ClearField(self, field_name: typing_extensions___Literal[u"AThing",b"AThing"]) -> None: ... The second way is similar, using a nested message Bar {
int64 X = 1;
}
message Foo {
Bar Bar = 1;
} which results in the following # definition of Bar
# ...
class Foo(google___protobuf___message___Message):
DESCRIPTOR: google___protobuf___descriptor___Descriptor = ...
@property
def Bar(self) -> Bar: ...
def __init__(self,
*,
Bar : typing___Optional[Bar] = None,
) -> None: ...
if sys.version_info >= (3,):
@classmethod
def FromString(cls, s: builtin___bytes) -> Foo: ...
else:
@classmethod
def FromString(cls, s: typing___Union[builtin___bytes, builtin___buffer, builtin___unicode]) -> Foo: ...
def MergeFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
def CopyFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
if sys.version_info >= (3,):
def HasField(self, field_name: typing_extensions___Literal[u"Bar"]) -> builtin___bool: ...
def ClearField(self, field_name: typing_extensions___Literal[u"Bar"]) -> None: ...
else:
def HasField(self, field_name: typing_extensions___Literal[u"Bar",b"Bar"]) -> builtin___bool: ...
def ClearField(self, field_name: typing_extensions___Literal[u"Bar",b"Bar"]) -> None: ... and the following test case reproduces the error message from my original comment: from foo_pb2 import Bar, Foo
x: Foo = Foo(Bar=Bar(X=123)) This can also be fixed by defining an alias like While using a field that has the same name as a type is admittedly not a great pattern, unfortunately we are stuck with it since we are already using these types in production. Is there any workaround we could do here? |
yeah - this seems like a totally reasonable concern - that may be avoidable by autogenerating an alias. We already generate some aliases like Great bugreport and analysis |
@forestbelton - mind taking a look at #112 to see if it handles the case you've brought up here (There are tests which should help illustrate). |
@nipunn1313, #112 looks like it will cover these above cases. Thanks for the quick turnaround! |
Hi,
Thank you for this wonderful project. I'm integrating mypy with a codebase that uses protobufs and feel that this will be quite helpful in doing so!
I'm able to generate the
*.pyi
type stub files along with the other definitions by invoking the following command:The generated
*.pyi
files look correct, however when I try to runmypy
over modules that import these definitions, I receive error messages like the following (names/line #s scrubbed):Inside of
foo_pb2.py
,Foo
is defined like follows:Is there something obvious I'm doing wrong? I'm using the following versions for my dependencies:
Thanks!
The text was updated successfully, but these errors were encountered: