Код: Выделить всё
from __future__ import annotations
from datetime import datetime, UTC
from typing import Any, Generic, Self, TypeVar
from pydantic import AwareDatetime, BaseModel
EventDataT_co = TypeVar('EventDataT_co', covariant=True)
class Event(BaseModel, Generic[EventDataT_co]):
raised_at: AwareDatetime
data: tuple[EventDataT_co, ...]
@classmethod
def from_data(cls, *data: EventDataT_co) -> Self:
return cls(raised_at=datetime.now(UTC), data=data)
def save_events(*events: Event): ... # not type-safe (someone might make unsafe assumption on `.data`)
def save_events(*events: Event[Any]): ... # same
def save_events(*events: Event[object]): ... # Only allowed if Event is covariant, but then I can't have a custom constructor
def save_events(*events: Event[EventDataT_co]): ... # It implies this is a generic function, when it's more `.data`-agnostic
Я понятия не имею, как это решить. Признаюсь, я новичок в концепции дисперсии, и мне неясно, делаю ли я что-то не так (является ли Event даже ковариантным с самого начала), или mypy нет позволяя что-то, что должно. Я стараюсь избегать использования Any здесь, потому что save_events на самом деле является методом другого класса, который может быть подклассом, и я бы не хотел, чтобы разработчик, который наследует от него, был укушен моим использование Any. Событие[object] кажется самым безопасным, но оно требует ковариации. Это не только означает отсутствие специального конструктора (я думаю), но также означает фактическую ковариацию, и я не уверен, что мой класс событий является ковариантным за пределами этого конкретного использования с объектом (т.е.: я не вижу использования случай, когда функция handle_foo_created(event: Event[FooParent]) должна когда-либо принимать Event[FooChild], и я не думаю, что событие: FooParentEvent = FooParentEvent.from_data(FooChild()) является вариант использования, который я хочу поддержать, но возможно, что и здесь я ошибаюсь).
Подробнее здесь: https://stackoverflow.com/questions/786 ... s-in-pytho