You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[1.16 regression] no longer recognizes enum singleton as only possible case #19271
I have an enum class Raise that has a single member, Raise._. I use this as a pattern to indicate that a function argument, if not specified, will default to raising an exception. Essentially it serves as an alternative to None, which a caller might want to explicitly pass. The following used to work in 1.15 but 1.16 complains.
from enum import Enum
from os import environ
from typing import final, TypeVar, Union
@final # 1.16 fails with or without this.
class Raise(Enum):
'''
A singleton value to indicate that the default behavior is to raise an exception.
'''
_ = 0
def get_some_config_val(default:str|Raise=Raise._) -> str:
'''
Get some config value or return the default. If default is not specified,
then raise an exception.
'''
try:
return environ['SOME_CONFIG_VAL']
except KeyError:
if default is Raise._: raise
return default
In 1.15 it appears that that mypy understood that Raise._ was the only value of type Raise. In 1.16 that returns error: Incompatible return value type (got "str | Raise", expected "str") [return-value].
Note that originally I did not have the @final decoration. After some reading I am unsure whether or not it should be required for this example to work, but it does not seem to affect the behavior of either 1.15 or 1.16. It would seem that the @Final should be necessary for mypy to recognize that Raise._ is the only possible value of type Raise, unless it was proving to itself that there is no subclass of Raise.
Obviously, I can change the implementation to if is instance(Raise._, Raise): raise, but there is an apparent loss of sophistication in 1.16 so I thought it was worth reporting.
changed the title [-]Possible 1.16 regression: no longer recognizes enum singleton as only possible case[/-][+][1.16 regression] no longer recognizes enum singleton as only possible case[/+]on Jun 10, 2025
Wow, and this is rather important - such enums are commonly used as sentinel values, like SENTINEL = object() but with type checker support. I'm surprised none of our tests have identified this regression.
Wow, and this is rather important - such enums are commonly used as sentinel values, like SENTINEL = object() but with type checker support. I'm surprised none of our tests have identified this regression.
This is only for things named _
Note that originally I did not have the @final decoration. After some reading I am unsure whether or not it should be required for this example to work, but it does not seem to affect the behavior of either 1.15 or 1.16.
No, you cannot subclass enums with members. Enums are implicitly final.
Activity
brianschubert commentedon Jun 10, 2025
Bisects to #18675, cc @sobolevn
[-]Possible 1.16 regression: no longer recognizes enum singleton as only possible case[/-][+][1.16 regression] no longer recognizes enum singleton as only possible case[/+]sterliakov commentedon Jun 10, 2025
Wow, and this is rather important - such enums are commonly used as sentinel values, like
SENTINEL = object()but with type checker support. I'm surprised none of our tests have identified this regression.A5rocks commentedon Jun 11, 2025
This is only for things named
_No, you cannot subclass enums with members. Enums are implicitly final.
sterliakov commentedon Jun 11, 2025
@A5rocks Ough, I haven't noticed that this only happens for members named literally
_. Nice catch! I wouldn't have tried to rename the member.Single underscore is not a sunder (#19273)
Single underscore is not a sunder (#19273)