Skip to content

Enum instance attributes are treated as class attributes #1920

Open
@SquidDev

Description

@SquidDev

Version info

Details

Putting type annotations on attribute assignments inside an enum causes those attributes to be treated as Enum members, rather than attributes.

For instance, consider a my_enum.py:

import enum

class MyEnum(enum.Enum):
    def __init__(self, value: int):
        self.x: int = value

    X = 1
    Y = 2

And our entrypoint file:

from typing import assert_never

from my_enum import MyEnum


def consume(x: MyEnum) -> bool:
    match x:
        case MyEnum.X | MyEnum.Y:
            return True
        case y:
            assert_never(y)

Running pytype on this prints the following error:

testcase/main.py:11:13: error: in consume: Function typing.assert_never was called with the wrong arguments [wrong-arg-types]
         Expected: (arg: empty, ...)
  Actually passed: (arg: my_enum.MyEnum)

            assert_never(y)
            ~~~~~~~~~~~~~~~

However, if we replace the self.x: int = value with self.x = value, then this type checks successfully.

This does not happen when the enum is in the same file, and appears to be an issue with how things are serialised to a .pyi file. With the type annotation, we get the following interface file:

# (generated with --quick)

import enum
from typing import Literal

class MyEnum(enum.Enum):
    X: Literal[1]
    Y: Literal[2]
    x: int
    def __init__(self, value: int) -> None: ...

Without the type annotation, x is instead inferred to be x: Annotated[int, 'property'].

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions