Description
I'd like to request that the TC consider adoption of a new chapter in the typing spec that spells out type checking behaviors related to enum classes.
Links to PR & Discussion
The PR can be found here. The latest draft incorporates feedback from PR reviews and the discussion.
The discussion can be found here.
TC Sign-off
- Eric
- Carl
- Jelle
- Rebecca
- Shantanu
Current Type Checker Behaviors
The proposed chapter specifies several required behaviors for type checkers along with some optional behaviors.
The latest published version of pyright (1.1.347) has about eight areas where it fails to conform with the required behaviors. Version 1.1.348 of pyright will address all of these.
The latest published version of mypy (1.8.0) mostly conforms to the proposed spec, but it doesn't yet implement support for enum.member
and enum.nonmember
, which were introduced in Python 3.11. It also doesn't enforce naming consistency when the functional form of Enum
is used. And it doesn't enforce the type of the _value_
attribute in all cases if _value_
has an annotated type.
I haven't done a detailed analysis of pyre or pytype, but I assume that they largely conform with the required parts of the proposed spec.
Controversial Issues
There is one potentially controversial issue raised in the proposed spec. It has to do with the way enum members and non-member attributes are delineated in a type stub. Historically, there has been no unambiguous way to differentiate between enum members and non-member attributes within a type stub.
Typeshed stubs (and presumably stubs outside of typeshed) are inconsistent in how they define enums.
class E1(Enum):
a = 1 # This is clearly intended to be a member
class E2(Enum):
a: int # This is ambiguous; is it a member of a non-member attribute?
class E3(Enum):
a = 1
b: int # ???
The proposed wording clears up this ambiguity and indicates that stubs should follow the same rules as non-stub files for differentiating between enum members and non-member attributes, but it allows the member value to be replaced with a ...
.
Fixing all of typeshed's stubs to conform with this updated spec will be relatively easy. I was able to do it in about 10 minutes, and the resulting changes are backward compatible with existing type checker implementations. However, once type checkers are updated to conform to the proposed spec, they will interpret older stubs differently than they do today. This could result in some temporary pain for users.
I don't have a good solution to this backward compatibility issue other than to recommend that type checkers may want to hold off on that part of the change while type stubs are updated.