Skip to content

Commit

Permalink
Changed the handling of Enum subclasses that explicitly override `v…
Browse files Browse the repository at this point in the history
…alue` or `name` to avoid using the special-case logic for computing these types. This is done regardless of whether the class uses a custom metaclass. This addresses #7939. (#7941)
  • Loading branch information
erictraut authored May 17, 2024
1 parent 7699780 commit c345c56
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
14 changes: 14 additions & 0 deletions packages/pyright-internal/src/analyzer/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,13 @@ export function getTypeOfEnumMember(
const literalValue = classType.literalValue;

if (memberName === 'name' || memberName === '_name_') {
// Does the class explicitly override this member? Or it it using the
// standard behavior provided by the "Enum" class?
const memberInfo = lookUpClassMember(classType, memberName);
if (memberInfo && isClass(memberInfo.classType) && !ClassType.isBuiltIn(memberInfo.classType, 'Enum')) {
return undefined;
}

const strClass = evaluator.getBuiltInType(errorNode, 'str');
if (!isInstantiableClass(strClass)) {
return undefined;
Expand Down Expand Up @@ -579,6 +586,13 @@ export function getTypeOfEnumMember(
const valueType = getEnumDeclaredValueType(evaluator, classType);

if (memberName === 'value' || memberName === '_value_') {
// Does the class explicitly override this member? Or it it using the
// standard behavior provided by the "Enum" class?
const memberInfo = lookUpClassMember(classType, memberName);
if (memberInfo && isClass(memberInfo.classType) && !ClassType.isBuiltIn(memberInfo.classType, 'Enum')) {
return undefined;
}

// If the enum class has a custom metaclass, it may implement some
// "magic" that computes different values for the "_value_" attribute.
// This occurs, for example, in the django TextChoices class. If we
Expand Down
26 changes: 26 additions & 0 deletions packages/pyright-internal/src/tests/samples/enum1.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,29 @@ class TestEnum20(Enum):
reveal_type(TestEnum20.A.A.A, expected_text="Literal[TestEnum20.A]")
reveal_type(TestEnum20.A.B.A, expected_text="Literal[TestEnum20.A]")
reveal_type(TestEnum20.A.B, expected_text="Literal[TestEnum20.B]")


class TestEnum21Base(Enum, metaclass=CustomEnumMeta1):
@property
def value(self) -> str:
return "test"


class TestEnum21(TestEnum21Base):
A = 1


reveal_type(TestEnum21.A.value, expected_text="str")


class TestEnum22Base(Enum):
@property
def value(self) -> str:
return "test"


class TestEnum22(TestEnum22Base):
A = 1


reveal_type(TestEnum22.A.value, expected_text="str")

0 comments on commit c345c56

Please sign in to comment.