[python] PY-59260 False positive assigining IntFlag enum value to an annotated variable

(cherry picked from commit 1b231b0917c41032255e90b3f524fc3d6201e80e)

IJ-CR-181224

GitOrigin-RevId: e2969be0fd18d29a1c2ba00a7ac3ad1a87edf79e
This commit is contained in:
chbndrhnns
2025-11-03 22:58:33 +00:00
committed by intellij-monorepo-bot
parent 5c2d6c3db3
commit 5579292ff3
2 changed files with 160 additions and 10 deletions
@@ -1618,4 +1618,116 @@ public class PyTypeCheckerInspectionTest extends PyInspectionTestCase {
z: type[None] = NoneType
"""));
}
// PY-59260
public void testIntFlagValueType() {
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() ->
doTestByText("""
from enum import IntFlag, auto
# IntFlag should infer int
class IF(IntFlag):
FIRST = auto()
SECOND = auto()
THIRD = 42
# IntFlag.value should return int, so these should not produce type errors
variable: int = IF.FIRST.value
another_var: int = IF.SECOND.value
explicit_var: int = IF.THIRD.value
# This should produce a type error
wrong_var: str = <warning descr="Expected type 'str', got 'int' instead">IF.FIRST.value</warning>
"""));
}
// PY-59260
public void testEnumValueTypeInference() {
runWithLanguageLevel(
LanguageLevel.getLatest(),
() ->
doTestByText("""
from enum import Enum, IntFlag, StrEnum
# IntFlag should infer int
class IF(IntFlag):
A = 1
i: int = IF.A.value
# StrEnum should infer str
class SE(StrEnum):
B = "b"
s: str = SE.B.value
# str mixin should infer str
class StrMixin(str, Enum):
C = "c"
s2: str = StrMixin.C.value
s3: int = <warning descr="Expected type 'int', got 'str' instead">StrMixin.C.value</warning>
# Empty str mixin should also infer str
class EmptyStrMixin(str, Enum):
pass
def test_empty(x: EmptyStrMixin):
s4: str = x.value
i2: int = <warning descr="Expected type 'int', got 'str' instead">x.value</warning>
"""));
}
// PY-59260
public void testEmptyEnumValueTypes() {
runWithLanguageLevel(
LanguageLevel.PYTHON311,
() ->
doTestByText("""
from enum import StrEnum, Enum
class EmptyStrEnum(StrEnum):
pass
class EmptyStrMixin(str, Enum):
pass
def test_empty_str_enum(x: EmptyStrEnum):
s: str = x.value
i: int = <warning descr="Expected type 'int', got 'str' instead">x.value</warning>
def test_empty_str_mixin(x: EmptyStrMixin):
s: str = x.value
i: int = <warning descr="Expected type 'int', got 'str' instead">x.value</warning>
"""));
}
// PY-59260
public void testEnumValueTypeIgnoresNonMembers() {
runWithLanguageLevel(
LanguageLevel.getLatest(),
() ->
doTestByText("""
from enum import Enum, nonmember
# Simple enum with just integer members
class SimpleEnum(Enum):
A = 1
B = 2
# Should infer int
x: int = SimpleEnum.A.value
y: str = <warning descr="Expected type 'str', got 'int' instead">SimpleEnum.B.value</warning>
# Enum with non-member first, then actual members
class E(Enum):
# This should be classified as a non-member
HELPER_CONSTANT = nonmember("not a member")
# These are the actual members - should infer int from first member
FIRST_MEMBER = 42
SECOND_MEMBER = 43
# Should infer int from FIRST_MEMBER (ignoring HELPER_CONSTANT)
a: int = E.FIRST_MEMBER.value
b: str = <warning descr="Expected type 'str', got 'int' instead">E.SECOND_MEMBER.value</warning>
"""));
}
}