-
Notifications
You must be signed in to change notification settings - Fork 15.5k
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
[Python] Provide a type alias ValueType on EnumTypeWrapper for mypy-protobuf compatibility #8182
[Python] Provide a type alias ValueType on EnumTypeWrapper for mypy-protobuf compatibility #8182
Conversation
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed (or fixed any issues), please reply here with What to do if you already signed the CLAIndividual signers
Corporate signers
ℹ️ Googlers: Go here for more info. |
@googlebot I signed it! |
Hi! Ping on this^ |
This would allow us to cleanup some code as well. :) |
c55ee08
to
c98029d
Compare
@nipunn1313 can you please add a label? It seems to be the only missing thing before this can be merged. |
This is quite old, so I'm gonna run the tests to make sure it's still viable. |
Hi! I'm not an official contributor on the project, so it was not clear to me how to add a label. I can rebase it to make sure things still work! Thanks for taking a look. |
No prob! I am :) Looks like all the builds failed, if you wanna fix up this PR I'll have someone take a look at it. |
c98029d
to
4e45b46
Compare
I believe it needs a label "release notes: yes" - so that it's automatically added to release notes. Can you run the tests once again (I rebased onto master and updated the PR). I don't have the ability to approve running workflows: First-time contributors need a maintainer to approve running workflows. Learn more. |
hi - it appears that the Kokoro tests are failing on master. I spun up a dev environment on linux and confirmed that
is failing I submitted a separate patch to address that in #8789 |
as far as I can tell from poking around there are at least a handful of other unrelated build issues that exist on master. |
# to be typed with more constraint | ||
# Eg. | ||
# def Name(self, number: MyGeneratedEnum.V) -> str | ||
V = int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer a more explicit name like ValueType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi - since this is for compatibility with https://github.com/dropbox/mypy-protobuf - this is a bit of a large non-backward compatible suggestion unfortunately.
It has the ergonomic downside of having very lengthy type names that don't end up being much more useful (IMO). In either case, you get an error from mypy of the form:
incompatible type "MyGeneratedEnum"; expected "ValueType"
incompatible type "MyGeneratedEnum"; expected "V"
both of which require some amount of looking inside the generated mypy-protobuf .pyi
to understand. I believe there is a common confusion amongst protobuf users that MyGeneratedEnum
is also an int
, when protobuf generates it as an EnumTypeWrapper
. I'm hoping that mypy-protobuf + this change helps avoid bugs related to that confusion.
Here's an example .proto
enum (OuterEnum) https://github.com/dropbox/mypy-protobuf/blob/master/proto/testproto/test.proto#L11
And the corresponding generated .pyi
in mypy-protobuf OuterEnum.V
https://github.com/dropbox/mypy-protobuf/blob/master/test/generated/testproto/test_pb2.pyi.expected#L25
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mypy-protobuf has this documented here https://github.com/dropbox/mypy-protobuf#types-enum-int-values-more-strongly.
If we do want to change the V
to something else, it could be possible via a compatibility version supporting both V
and ValueType
types and eventually dropping support for V
. I know Dropbox alone has thousands of instances of V
already, as do other companies/codebases using mypy+protobuf. I'm hesitant to do such a change without some strong feedback + consensus - to avoid churning on name changes here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an unfortunate situation... and the approach looks a bit backwards to me: mypy should not require changes to Python or common libraries.
But if I got this correctly, all current usages need quotes, as in: def f(x: 'MyEnum.V')
and this V
is provided by mypy-protobuf generated code.
Since removing the quotes is a change anyway, the recommended end state could be def f(x: MyEnum.ValueType)
(no quotes, but longer name), and the V
would be supported by mypy as an alias (shorter, but with quotes)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an unfortunate situation... and the approach looks a bit backwards to me: mypy should not require changes to Python or common libraries.
Agreed.
The reason this comes up is because mypy-protobuf
is attempting to get stronger typing than what protobuf itself generates at runtime. Protobuf generates all enum values as int
. The stronger typing has proven to catch bugs and is one of the value adds of mypy-protobuf, but in order to namespace the NewType("ValueType", int)
into MyEnum
, it requires this change.
Starting with python 3.10 there is a new feature for postponed evaluation of annotations
https://www.python.org/dev/peps/pep-0563/
(or starting in python 3.7 with from __future__ import annotations
)
However, there are still cases where this is insufficient to avoid evaluation - notably
from typing import cast
cast(MyEnum.ValueType, x)
Since removing the quotes is a change anyway, the recommended end state could be def f(x: MyEnum.ValueType) (no quotes, but longer name), and the V would be supported by mypy as an alias (shorter, but with quotes)
I'm happy with your suggestion for a backward-compatible way to move toward a more verbose name. I can work with that in mypy-protobuf
. @amauryfa - are you a review authority here? I can make the change. Just want to make sure I avoid discussion churn on these sorts of points.
Side note: There is an alternate python generated code option that sidestepped this problem entirely by generating enum values as enums https://github.com/danielgtaylor/python-betterproto. I've never tried it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the diff with this idea of s/V/ValueType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@perezd can you approve running to workflow again?
This should provide a runtime alias, which can be used in mypy stubs to provide better typing for enum values Fixes protocolbuffers#8175
4e45b46
to
428ef16
Compare
@nipunn1313 Thanks! |
Cool. Just wanted to double check before this releases - are you happy with the name If people have preexisting proto enums with a field named Once the next major release of protobuf comes out with this, I'll modify mypy-protobuf to work with this! |
@anandolee and @haberman, does this naming sound ok? |
See protocolbuffers/protobuf#8182 which will make it into protobuf 3.20.0 Have to use a `V = Union[ValueType]` hax, because `V = ValueType` is interpreted as a value rather than alias `V: TypeAlias = ValueType` appears buggy within nested scopes. Fixes #169
See protocolbuffers/protobuf#8182 which will make it into protobuf 3.20.0 Have to use a `V = Union[ValueType]` hax, because `V = ValueType` is interpreted as a value rather than alias `V: TypeAlias = ValueType` appears buggy within nested scopes. Fixes #169
This should provide a runtime alias, which can be
used in mypy stubs to provide better typing for enum values
This is one potential solution to #8175 - see discussion there.
Fixes #8175