pythonprotocolspython-typingclass-variables

How to define a immutable ClassVar in a python protocol?


I have an Enum and several classes using that Enum in an immutable class variable.

from typing import ClassVar, Protocol, Final, Literal
from enum import Enum

class MyEnum(Enum):
    A = 0
    B = 1
    
class MyClass1:
    type: Final = MyEnum.A

class MyClass2:
    type: Final = MyEnum.B

This works fine but I fail to define a protocol encompassing the two classes. Both:

class MyProtocol1(Protocol):
    @property
    def type(self) -> MyEnum: ...

class MyProtocol2(Protocol):
    type: Final[MyEnum]

do not work for obvious reasons.

class MyProtocol3(Protocol):
    @property
    def type(self) -> ClassVar[MyEnum]: ...

class MyProtocol4(Protocol):
    @property
    @classmethod
    def type(cls) -> MyEnum: ...

might achieve what I want but are not allowed. I thought about using a Generic with Literal, which also led nowhere. I am running out of ideas.


Solution

  • The way to spell a read-only class variable within a protocol is:

    class MyProtocol1(Protocol):
        type: ClassVar[ReadOnly[MyEnum]]
    

    This usage follows the semantics defined by PEP 767, which is currently in draft and not supported by any type checkers.