0

I have the following abstract Data class and some concrete subclasses:

import abc
from typing import TypeVar, Generic, Union

from pydantic import BaseModel

T = TypeVar('T')


class Data(BaseModel, abc.ABC, Generic[T]):
    def handle(self, data: T) -> None:
        raise NotImplementedError()


class StringData(Data[str]):
    name: str = "string"

    def handle(self, data: str) -> None:
        print("String data:", data)


class IntData(Data[int]):
    name: str = "int"

    def handle(self, data: int) -> None:
        print("Int data:", data)

Now I want a DataManager class that can hold any Data subclass and delegate handle calls.

Note that I must use a Union instead of the abstract class so that model_dump_json actually produces the correct result. It’s not ideal, but it seems like there’s no way around it.

U = TypeVar('U')

class DataManager(BaseModel, Generic[U]):
    my_data: Union[StringData, IntData] # Good
    my_data: Data # NOT GOOD!

So after this step, let's say we have:

class DataManager(BaseModel, Generic[U]):
    my_data: Union[StringData, IntData]

    def handle(self, data: U) -> None:
        self.my_data.handle(data)

class StringDataManager(DataManager[str]):
    pass

StringDataManager(my_data=StringData()).handle(data="some-string")

This seems valid because each DataManager subclass corresponds to the type of its data. So when calling handle, everything works at runtime — for example, using as string manager will set 'U' to string that will be pass 'string' to the StringData handle function perfectly. However, mypy fails here because it thinks we’re passing U, even though we are actually passing the correct type.

Argument 1 to "handle" of "StringData" has incompatible type "U"; expected "str" [arg-type]

Argument 1 to "handle" of "IntData" has incompatible type "U"; expected "int" [arg-type]

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.