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
Is Enum's _generate_next_value_ really a @staticmethod? #10428
I was playing around with a custom enum and wanted to give it custom auto values. But come time to override _generate_next_value_ and pyright tells me that: Method "_generate_next_value_" overrides class "Enum" in an incompatible manner. Base method is declared as a staticmethod but override is not.
mypy:
error: Signature of "_generate_next_value_" incompatible with supertype "Enum" [override]
note: Superclass:
note: def _generate_next_value_(name: str, start: int, count: int, last_values: list[Any]) -> Any
note: Subclass:
note: def _generate_next_value_(name, *_: Any) -> Any
The following code in Python 3.9 works as expected, although with a type error:
fromenumimportEnum, EnumMeta, auto, uniquefromtypingimportcastfromtyping_extensionsimportoverrideclassCaptureMethodMeta(EnumMeta):
# Allow checking if simple string is enum@overridedef__contains__(self, other: object):
try:
self(other)
exceptValueError:
returnFalsereturnTrue@unique# TODO: Replace with StrEnum in Python 3.11classCaptureMethodEnum(str, Enum, metaclass=CaptureMethodMeta):
# Allow TOML to save as a simple string@overridedef__repr__(self):
returnself.value__str__=__repr__@overridedef_generate_next_value_(name: str, *_):
returnnameNONE=""BITBLT=auto()
WINDOWS_GRAPHICS_CAPTURE=auto()
PRINTWINDOW_RENDERFULLCONTENT=auto()
DESKTOP_DUPLICATION=auto()
VIDEO_CAPTURE_DEVICE=auto()
bitblt: str=cast(str, "BITBLT")
bar: str=cast(str, "bar")
print(bitblt==CaptureMethodEnum.BITBLT)
print(bar==CaptureMethodEnum.BITBLT)
print("BITBLT"inCaptureMethodEnum)
print("bar"inCaptureMethodEnum)
If I decorate _generate_next_value_ with @staticmethod, I get the following error:
Traceback (most recent call last):
File "c:\Users\Avasam\Desktop\from enum import Enum, EnumMeta, unique.py", line 18, in <module>
class CaptureMethodEnum(str, Enum, metaclass=CaptureMethodMeta):
File "c:\Users\Avasam\Desktop\from enum import Enum, EnumMeta, unique.py", line 31, in CaptureMethodEnum
BITBLT = auto()
File "C:\Program Files\Python39\lib\enum.py", line 142, in __setitem__
value.value = self._generate_next_value(
TypeError: 'staticmethod' object is not callable
I haven't looked at this in depth, but considering the highly "custom" nature of enums, it's quite possible that this was/is a hack to make things work. That said, it never hurts to check whether hacks are still necessary and remove them if not. At least, there should be a comment explaining the necessity of a hack.
This looks like a duplicate of python/mypy#7591, but the mypy bug does not have a lot of details. From a quick look, I found that:
_generate_next_value_ is a de-facto @staticmethod, but the docs did not decorate it until python 3.11. See python 3.10 docs, python 3.11 docs.
Until python 3.10, decorating _generate_next_value_ produced an error at runtime that can be seen in the OP. However, this only happens when _generate_next_value_ is defined directly in the class. If you instead define it in a base class, decorating the method works fine.
In short, move it to a base class and use @staticmethod. This is probably what you want anyway, since it allows you to package and reuse this functionality.
Hum, if all that is correct, I wonder if typeshed should only decorate _generate_next_value_ with @staticmethod for python 3.10 or above. So that a user's type-checker doesn't tell them to decorate it, which would fail at runtime.
In fact it would warn the user of "incompatible override" if they decorated it.
If you don't decorate it, you'll hit another problem. It will be considered an instance method, and you'll get an error that the first argument's type is wrong. See the mypy bug I linked above.
I believe _generate_next_value_ should be decorated with @staticmethod. But that crashes in python 3.8 and 3.9 . Not sure if that can be fixed on the type-definition side (see python/typeshed#10428)
Activity
srittau commentedon Jul 10, 2023
I haven't looked at this in depth, but considering the highly "custom" nature of enums, it's quite possible that this was/is a hack to make things work. That said, it never hurts to check whether hacks are still necessary and remove them if not. At least, there should be a comment explaining the necessity of a hack.
eltoder commentedon Jul 11, 2023
This looks like a duplicate of python/mypy#7591, but the mypy bug does not have a lot of details. From a quick look, I found that:
_generate_next_value_is a de-facto@staticmethod, but the docs did not decorate it until python 3.11. See python 3.10 docs, python 3.11 docs._generate_next_value_produced an error at runtime that can be seen in the OP. However, this only happens when_generate_next_value_is defined directly in the class. If you instead define it in a base class, decorating the method works fine.In short, move it to a base class and use
@staticmethod. This is probably what you want anyway, since it allows you to package and reuse this functionality.Avasam commentedon Jul 12, 2023
Hum, if all that is correct, I wonder if typeshed should only decorate
_generate_next_value_with@staticmethodfor python 3.10 or above. So that a user's type-checker doesn't tell them to decorate it, which would fail at runtime.In fact it would warn the user of "incompatible override" if they decorated it.
eltoder commentedon Jul 12, 2023
If you don't decorate it, you'll hit another problem. It will be considered an instance method, and you'll get an error that the first argument's type is wrong. See the mypy bug I linked above.
jenstroeger commentedon Aug 15, 2025
Maybe somewhat related discussion: Typing the
_missing_method of an StrEnum’s sub-classAvasam commentedon May 18, 2026
python/mypy#15382 (comment)
Since typeshed also dropped Python 39 support (#15708) I'll just close this as my issue "fixed itself"