admin管理员组文章数量:1291045
disclaimer: will refer to EnumType
as opposed to the older EnumMeta
The following is valid at runtime (and is typically what is recommended to do):
import sys
from enum import Enum, IntEnum
from typing import Any, Type, TypeVar, Union, Callable, cast, TYPE_CHECKING
if sys.version_info >= (3, 11):
from enum import EnumType
else:
from enum import EnumMeta as EnumType
_E = TypeVar("_E", bound=Enum)
class MultipleEnumAccessMeta(EnumType):
"""
Enum Metaclass to provide a way to access multiple values all at once.
"""
def __getitem__(cls: Type[_E], key: Union[str, tuple[str, ...]]) -> Union[_E, list[_E]]:
getitem = cast(Callable[[Type[_E], str], _E], EnumType.__getitem__) # Ensure correct typing for __getitem__
if isinstance(key, tuple):
return [getitem(cls, name) for name in key] # Return list for tuple keys
return getitem(cls, key) # Return single value for single key
if TYPE_CHECKING:
reveal_type(EnumType.__getitem__) # Base method signature
reveal_type(MultipleEnumAccessMeta.__getitem__) # Overridden method signature
# Test Enum with metaclass
class Names(IntEnum, metaclass=MultipleEnumAccessMeta):
Alice = 0
Bob = 1
Charlie = 2
# Test cases
assert Names["Alice"] == Names.Alice
assert Names["Alice", "Bob"] == [Names.Alice, Names.Bob]
However, this gives the following typehint complaints
test.py:17: error: Self argument missing for a non-static method (or an invalid type for self) [misc]
test.py:17: error: Return type "list[Never]" of "__getitem__" incompatible with return type "Never" in supertype "EnumMeta" [override]
test.py:25: note: Revealed type is "def [_EnumMemberT] (type[_EnumMemberT`3], builtins.str) -> _EnumMemberT`3"
test.py:26: note: Revealed type is "def [_E <: enum.Enum] (type[_E`4], Union[builtins.str, tuple[builtins.str, ...]]) -> Union[_E`4, builtins.list[_E`4]]"
test.py:36: error: Enum index should be a string (actual index type "tuple[str, str]") [misc]
test.py:36: error: Non-overlapping equality check (left operand type: "Names", right operand type: "list[Names]") [comparison-overlap]
So to first order, you say "fine", if I drop the cls: Type[_E]
portion type-hint, mypy
gets more confused:
test.py:17: error: Return type "Union[_E, list[_E]]" of "__getitem__" incompatible with return type "Never" in supertype "EnumMeta" [override]
test.py:21: error: Argument 1 has incompatible type "MultipleEnumAccessMeta"; expected "type[_E]" [arg-type]
test.py:22: error: Argument 1 has incompatible type "MultipleEnumAccessMeta"; expected "type[_E]" [arg-type]
test.py:25: note: Revealed type is "def [_EnumMemberT] (type[_EnumMemberT`3], builtins.str) -> _EnumMemberT`3"
test.py:26: note: Revealed type is "def [_E <: enum.Enum] (atlas_schema.test.MultipleEnumAccessMeta, Union[builtins.str, tuple[builtins.str, ...]]) -> Union[_E`4, builtins.list[_E`4]]"
test.py:36: error: Enum index should be a string (actual index type "tuple[str, str]") [misc]
test.py:36: error: Non-overlapping equality check (left operand type: "Names", right operand type: "list[Names]") [comparison-overlap]
I have questions. Likely this is partially due to the metaclassing that's being very tricky and I'm doing my best to be careful here, but I'm apparently either not careful enough or mypy
really has some bugs:
- why is
EnumType.__getitem__
revealed as both returningNever
and_EnumMemberT`3
? This seems like a weird internal conflict withmypy
. - How do we typehint the
cls
parameter ofMultipleEnumAccessMeta.__getitem__
correctly, both to ensure theTypeVar
is evaluated consistently bymypy
, but also so that the call tosuper().__getitem__
[or toEnumType.__getitem__
] is correct?
本文标签: pythonHow can I get mypy to handle subclassing EnumTypeEnumMeta correctlyStack Overflow
版权声明:本文标题:python - How can I get mypy to handle subclassing EnumTypeEnumMeta correctly? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741504425a2382235.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论