|
4 | 4 | """ |
5 | 5 |
|
6 | 6 | from typing import List, Tuple, Optional, Union, cast |
| 7 | +from typing_extensions import Final |
7 | 8 |
|
8 | 9 | from mypy.nodes import ( |
9 | 10 | Expression, Context, TypeInfo, AssignmentStmt, NameExpr, CallExpr, RefExpr, StrExpr, |
|
13 | 14 | from mypy.semanal_shared import SemanticAnalyzerInterface |
14 | 15 | from mypy.options import Options |
15 | 16 |
|
| 17 | +# Note: 'enum.EnumMeta' is deliberately excluded from this list. Classes that directly use |
| 18 | +# enum.EnumMeta do not necessarily automatically have the 'name' and 'value' attributes. |
| 19 | +ENUM_BASES: Final = frozenset(( |
| 20 | + 'enum.Enum', 'enum.IntEnum', 'enum.Flag', 'enum.IntFlag', |
| 21 | +)) |
| 22 | +ENUM_SPECIAL_PROPS: Final = frozenset(( |
| 23 | + 'name', 'value', '_name_', '_value_', '_order_', '__order__', |
| 24 | +)) |
| 25 | + |
16 | 26 |
|
17 | 27 | class EnumCallAnalyzer: |
18 | 28 | def __init__(self, options: Options, api: SemanticAnalyzerInterface) -> None: |
@@ -62,7 +72,7 @@ class A(enum.Enum): |
62 | 72 | if not isinstance(callee, RefExpr): |
63 | 73 | return None |
64 | 74 | fullname = callee.fullname |
65 | | - if fullname not in ('enum.Enum', 'enum.IntEnum', 'enum.Flag', 'enum.IntFlag'): |
| 75 | + if fullname not in ENUM_BASES: |
66 | 76 | return None |
67 | 77 | items, values, ok = self.parse_enum_call_args(call, fullname.split('.')[-1]) |
68 | 78 | if not ok: |
|
0 commit comments