Skip to content

Commit 1fedf2c

Browse files
authored
Fix false-positive error on multiple enum base classes (#12963)
Fixes #12787. Mypy currently emits a false-positive error for this snippet of code, even though it works fine at runtime (and this exact inheritance structure is used in enum.py in the stdlib): ``` from enum import Enum, Flag class ReprEnum(Enum): ... class MyFlag(ReprEnum, Flag): ... ``` This PR fixes that.
1 parent b0c1556 commit 1fedf2c

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

mypy/checker.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -1965,14 +1965,29 @@ def is_final_enum_value(self, sym: SymbolTableNode) -> bool:
19651965
return False
19661966

19671967
def check_enum_bases(self, defn: ClassDef) -> None:
1968+
"""
1969+
Non-enum mixins cannot appear after enum bases; this is disallowed at runtime:
1970+
1971+
class Foo: ...
1972+
class Bar(enum.Enum, Foo): ...
1973+
1974+
But any number of enum mixins can appear in a class definition
1975+
(even if multiple enum bases define __new__). So this is fine:
1976+
1977+
class Foo(enum.Enum):
1978+
def __new__(cls, val): ...
1979+
class Bar(enum.Enum):
1980+
def __new__(cls, val): ...
1981+
class Baz(int, Foo, Bar, enum.Flag): ...
1982+
"""
19681983
enum_base: Optional[Instance] = None
19691984
for base in defn.info.bases:
19701985
if enum_base is None and base.type.is_enum:
19711986
enum_base = base
19721987
continue
1973-
elif enum_base is not None:
1988+
elif enum_base is not None and not base.type.is_enum:
19741989
self.fail(
1975-
f'No base classes are allowed after "{enum_base}"',
1990+
f'No non-enum mixin classes are allowed after "{enum_base}"',
19761991
defn,
19771992
)
19781993
break

test-data/unit/check-enum.test

+27-7
Original file line numberDiff line numberDiff line change
@@ -1903,6 +1903,14 @@ class Third:
19031903
class Mixin:
19041904
pass
19051905

1906+
class EnumWithCustomNew(enum.Enum):
1907+
def __new__(cls, val):
1908+
pass
1909+
1910+
class SecondEnumWithCustomNew(enum.Enum):
1911+
def __new__(cls, val):
1912+
pass
1913+
19061914
# Correct Enums:
19071915

19081916
class Correct0(enum.Enum):
@@ -1920,6 +1928,9 @@ class Correct3(Mixin, enum.Enum):
19201928
class RegularClass(Mixin, First, Second):
19211929
pass
19221930

1931+
class Correct5(enum.Enum):
1932+
pass
1933+
19231934
# Correct inheritance:
19241935

19251936
class _InheritingDataAndMixin(Correct1):
@@ -1934,42 +1945,51 @@ class _CorrectWithDataAndMixin(Mixin, First, Correct0):
19341945
class _CorrectWithMixin(Mixin, Correct2):
19351946
pass
19361947

1948+
class _CorrectMultipleEnumBases(Correct0, Correct5):
1949+
pass
1950+
1951+
class _MultipleEnumBasesAndMixin(int, Correct0, enum.Flag):
1952+
pass
1953+
1954+
class _MultipleEnumBasesWithCustomNew(int, EnumWithCustomNew, SecondEnumWithCustomNew):
1955+
pass
1956+
19371957
# Wrong Enums:
19381958

19391959
class TwoDataTypesViaInheritance(Second, Correct2): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Correct2"
19401960
pass
19411961

1942-
class TwoDataTypesViaInheritanceAndMixin(Second, Correct2, Mixin): # E: No base classes are allowed after "__main__.Correct2" \
1962+
class TwoDataTypesViaInheritanceAndMixin(Second, Correct2, Mixin): # E: No non-enum mixin classes are allowed after "__main__.Correct2" \
19431963
# E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Correct2"
19441964
pass
19451965

1946-
class MixinAfterEnum1(enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum"
1966+
class MixinAfterEnum1(enum.Enum, Mixin): # E: No non-enum mixin classes are allowed after "enum.Enum"
19471967
pass
19481968

1949-
class MixinAfterEnum2(First, enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum"
1969+
class MixinAfterEnum2(First, enum.Enum, Mixin): # E: No non-enum mixin classes are allowed after "enum.Enum"
19501970
pass
19511971

19521972
class TwoDataTypes(First, Second, enum.Enum): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second"
19531973
pass
19541974

1955-
class TwoDataTypesAndIntEnumMixin(First, Second, enum.IntEnum, Mixin): # E: No base classes are allowed after "enum.IntEnum" \
1975+
class TwoDataTypesAndIntEnumMixin(First, Second, enum.IntEnum, Mixin): # E: No non-enum mixin classes are allowed after "enum.IntEnum" \
19561976
# E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second"
19571977
pass
19581978

19591979
class ThreeDataTypes(First, Second, Third, enum.Enum): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \
19601980
# E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third"
19611981
pass
19621982

1963-
class ThreeDataTypesAndMixin(First, Second, Third, enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum" \
1983+
class ThreeDataTypesAndMixin(First, Second, Third, enum.Enum, Mixin): # E: No non-enum mixin classes are allowed after "enum.Enum" \
19641984
# E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \
19651985
# E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third"
19661986
pass
19671987

1968-
class FromEnumAndOther1(Correct2, Second, enum.Enum): # E: No base classes are allowed after "__main__.Correct2" \
1988+
class FromEnumAndOther1(Correct2, Second, enum.Enum): # E: No non-enum mixin classes are allowed after "__main__.Correct2" \
19691989
# E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second"
19701990
pass
19711991

1972-
class FromEnumAndOther2(Correct2, Second): # E: No base classes are allowed after "__main__.Correct2" \
1992+
class FromEnumAndOther2(Correct2, Second): # E: No non-enum mixin classes are allowed after "__main__.Correct2" \
19731993
# E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second"
19741994
pass
19751995
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)