I
I
Ilya Chichak2020-09-10 01:21:20
Python
Ilya Chichak, 2020-09-10 01:21:20

How to annotate the type of a class attribute to be overridden?

Let's say we have an abstract class:

import abc
from pydantic import BaseModel

class Abstract(abc.ABC):
    context_class: ClassVar[Type['BaseModel']]
    error: ClassVar[Type[Exception]]

    def __init__(self, data: Dict) -> None:
        self.context = self.context_class(**data)

    @abc.abstractmethod
    def process(self) -> None:
        pass


And there is its heir, in which the `context_class` attribute is overridden by the `BaseModel` heir:

class Context(BaseModel):
    email: str

class Concrete(Abstract):
    context_class = Context

    def process(self) -> None:
        print(self.context.email)


When starting Mypy - an error falls: how to correctly specify the type in an abstract class? Clarification: Python 3.8.2 Mypy 0.770 Pydantic 1.6.1
... error: "BaseModel" has no attribute "email"


Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
Ilya Chichak, 2020-09-10
@ilya_chch

Solution found:

import abc
from typing import ClassVar, Type, Dict, Generic, TypeVar
from pydantic import BaseModel

T = TypeVar('T', bound=BaseModel)


class Abstract(abc.ABC, Generic[T]):
    context_class: ClassVar[Type[T]]
    error: ClassVar[Type[Exception]]

    def __init__(self, data: Dict) -> None:
        self.context = self.context_class(**data)

    @abc.abstractmethod
    def process(self) -> None:
        pass


class Context(BaseModel):
    email: str


class Concrete(Abstract[Context]):
    context_class = Context

    def process(self) -> None:
        print(self.context.email)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question