Home > OS >  python3: type annotations and enum subclasses
python3: type annotations and enum subclasses

Time:10-01

I don't like getting complaints from Mypy about function signatures, but I don't know how to resolve this one.

I am building a package, that is to be used by several programs. I have a subclass of IntEnum (FWIW, called _Event), which contains a number of relevant properties and methods. _Event is never used directly, since it contains no members, but several different programs use incompatible subclasses of _Event (AlphaEvent, BetaEvent, etc.), which define the actual members of the Enum (i.e, the actual events). Only one member of each subclass is common, and as it happens, it's called END. Since you can't subclass an enum with members, it is defined in each subclass individually (so _Event has no END member, but AlphaEvent.END and BetaEvent.END exist).

I have several functions which utilise subclasses of _Event. I have a couple which need to access properties of the END member, but are generic to all instances. So they contain a signature:

def generic_event_func(events: _Event):
    ...
    events.END.action = <expr>

MyPy flags the last line of code above with "error: "_Event" has no attribute "END"

True enough, but the subclasses do. How do I annotate the function signature to remove this error?

CodePudding user response:

I faced a kinda similar issue recently and ended refactored using ABC. Not sure if you have latitude to refactor much, but maybe it can help in some way:

from abc import ABC, abstractmethod
from enum import Enum

class Event(Enum):
    a = EventA
    b = EventB
    c = EventC


class AbstractEvent(ABC):
    @abstractmethod
    def action(self):
        pass


class EventA(AbstractEvent):
    def action(self):
        ....


event_cls = Event["a"].value
event: Union[EventA, EventB, EventC] = event_cls()
event.action()

CodePudding user response:

I'm not (yet) an optional static typing person, but something like the following might work:

from typing import Any

class _Event(IntEnum):
    END: Any

End is now type hinted, but doesn't actually exist, so won't interfere with subclassing _Event.

  • Related