diff --git a/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml b/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml
index c60c79523a82..fff4307cdbf2 100644
--- a/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml
+++ b/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml
@@ -523,7 +523,8 @@
-
+
+
diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
index 25437ef8fe99..13860f1d7b30 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
@@ -110,10 +110,23 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
final PyReferenceExpression qualifierExpr = (PyReferenceExpression)qualifier;
final PsiElement resolvedQualifier = qualifierExpr.getReference().resolve();
if (resolvedQualifier instanceof PyTargetExpression) {
- final PyTargetExpression qualifierTarget = (PyTargetExpression)resolvedQualifier;
- // Requires switching to AST, we cannot use getType(qualifierTarget) here, because its type is overridden by this type provider
- if (context.maySwitchToAST(qualifierTarget)) {
- final PyExpression value = qualifierTarget.findAssignedValue();
+ final PyTargetExpression enumItem = (PyTargetExpression)resolvedQualifier;
+ // Requires switching to AST, we cannot use getType(enumItem) here, because its type is overridden by this type provider
+ if (context.maySwitchToAST(enumItem)) {
+ final PyExpression value = enumItem.findAssignedValue();
+ if (value != null) {
+ return context.getType(value);
+ }
+ }
+ }
+ }
+ else if (qualifier != null) {
+ PyClassType enumType = as(context.getType(qualifier), PyClassType.class);
+ if (enumType != null) {
+ PyClass enumClass = enumType.getPyClass();
+ PyTargetExpression firstEnumItem = ContainerUtil.getFirstItem(enumClass.getClassAttributes());
+ if (firstEnumItem != null && context.maySwitchToAST(firstEnumItem)) {
+ final PyExpression value = firstEnumItem.findAssignedValue();
if (value != null) {
return context.getType(value);
}
diff --git a/python/testSrc/com/jetbrains/python/PyTypeTest.java b/python/testSrc/com/jetbrains/python/PyTypeTest.java
index 8427150d31eb..251020dcfdaf 100644
--- a/python/testSrc/com/jetbrains/python/PyTypeTest.java
+++ b/python/testSrc/com/jetbrains/python/PyTypeTest.java
@@ -3979,6 +3979,36 @@ public class PyTypeTest extends PyTestCase {
);
}
+ // PY-54503
+ public void testEnumGetItemResultValueAttribute() {
+ runWithLanguageLevel(
+ LanguageLevel.getLatest(),
+ () -> doTest("int",
+ "import enum\n" +
+ "\n" +
+ "class MyEnum(enum.Enum):\n" +
+ " ONE = 1\n" +
+ " TWO = 2\n" +
+ "\n" +
+ "expr = MyEnum['ONE'].value")
+ );
+ }
+
+ // PY-54503
+ public void testEnumDunderCallResultValueAttribute() {
+ runWithLanguageLevel(
+ LanguageLevel.getLatest(),
+ () -> doTest("int",
+ "import enum\n" +
+ "\n" +
+ "class MyEnum(enum.Enum):\n" +
+ " ONE = 1\n" +
+ " TWO = 2\n" +
+ "\n" +
+ "expr = MyEnum(1).value")
+ );
+ }
+
private static List getTypeEvalContexts(@NotNull PyExpression element) {
return ImmutableList.of(TypeEvalContext.codeAnalysis(element.getProject(), element.getContainingFile()).withTracing(),
TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile()).withTracing());