-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Wrong enum value type inferred for members defined in a subclass (regression) #10000
Comments
I found some time to have a closer look today. So it seems that the proper fix would be to teach mypy to infer attributes from Instead, for the time being I propose to stop trying to make a clever guess if the enum class in question implements The other surprising part was why the bug was only exposed on the subclass. The reason for this is that in the parent class, I'm going to prepare a PR to fix the problem along these lines. |
In python#9443, some code was added to predict the type of enum values where it is not explicitly when all enum members have the same type. However, it didn't consider that subclasses of Enum that have a custom __new__ implementation may use any type for the enum value (typically it would use only one of their parameters instead of a whole tuple that is specified in the definition of the member). Fix this by avoiding to guess the enum value type in classes that implement __new__. In addition, the added code was buggy in that it didn't only consider class attributes as enum members, but also instance attributes assigned to self.* in __init__. Fix this by ignoring implicit nodes when checking the enum members. Fixes python#10000.
In #9443, some code was added to predict the type of enum values where it is not explicitly when all enum members have the same type. However, it didn't consider that subclasses of Enum that have a custom __new__ implementation may use any type for the enum value (typically it would use only one of their parameters instead of a whole tuple that is specified in the definition of the member). Fix this by avoiding to guess the enum value type in classes that implement __new__. In addition, the added code was buggy in that it didn't only consider class attributes as enum members, but also instance attributes assigned to self.* in __init__. Fix this by ignoring implicit nodes when checking the enum members. Fixes #10000. Co-authored-by: Kevin Wolf <mail@kevin-wolf.de>
user-defined data type class (with __new__). This fixes a regression introduced by python#10057 to fix python#10000. The `not ti.fullname.startswith("builtins.") clause seemed to be intended to catch enums with a built-in data type like int or bytes, but this is overly broad. It should allow any type so long as it is not itself an enum.Enum subclass.
Bug Report
I have an Enum base class with a
__new__
implementation with multiple parameters, so that for the declaration of members a tuple can be given, one of which is used as the value for the member. The members are only defined in a subclass (this is important for triggering the bug).In mypy 0.790, the value of the members is still inferred as Any, whereas in mypy 0.800 it incorrectly infers it as the whole tuple given at the declaration (it should use the type of the one tuple item that is assigned to
self._value_
in__new__()
).I have bisected the changed behaviour to commit 37777b3. Reverting only this commit on top of master is enough to get the old behaviour back.
To Reproduce
This can be reproduced with a slightly modified example from the Python documentation: https://docs.python.org/3/library/enum.html#when-to-use-new-vs-init
The modification is some added type hints and splitting the member definitions off into a child class (if they are defined in the same class, Any is still inferred).
At runtime (after commenting out reveal_type), this gives the expected result:
I'm running mypy with
mypy --strict /tmp/enum_new.py
, though strict isn't even needed for this one.Expected Behavior
The old behaviour before commit 37777b3 is not ideal because it infers Any, but I consider this acceptable:
Even better behaviour would be inferring
int
forc.value
.Actual Behavior
After commit 37777b3, and in mypy 0.800, this is result instead:
The inferred Tuple type is just wrong.
Your Environment
mypy.ini
(and other config files): noneThe text was updated successfully, but these errors were encountered: