'How to create a Python ABC interface pattern using Pydantic

I'm implementing a Python Interface using the abstract base class (known as the strategy pattern). I want to be able to do this with Pydantic.

Without Pydantic, I would use properties, like this:

from abc import ABC,  abstractproperty

@dataclass
class PersonEntity(ABC):

    @abstractproperty
    def first_name(self):
        raise NotImplementedError

    @abstractproperty
    def last_name(self):
        raise NotImplementedError


@dataclass
class Person(PersonEntity):

    @property
    def first_name(self):
        return 'Jimmy'

    @property
    def last_name(self):
        return 'Kelly'

This way, if I were to implement another class, like

@dataclass
class SillyPerson(PersonEntity):

    @property
    def first_name(self):
        return 'Jimmy'

    @property
    def last_name(self):
        return 'Kelly'

    @property
    def sillyness(self):
        return 5

then the interface will throw an error. This helps constrain any new class that inherits from PersonEntity.

However, I want to spit this information into a FastAPI response object. I cannot do this without figuring out some kind of serializer to grab all the values of each property field, and just the property fields (which I'm struggling to do).

I would rather use Pydantic. In this case, I dont need properties, I can simply do:

from pydantic import BaseModel


class PersonEntity(ABC, BaseModel):
    first_name: str
    last_name: str


class Person(PersonEntity):
    first_name: str
    last_name: str

These will serialize in the way that I need, but I lose the interface functionality because now I have no properties, and therefore cannot use @abstractproperty.

So if I were to implement

class SillyPerson(PersonEntity):
    first_name: str
    last_name: str
    sillyness: str

there's no error, because pydantic allows this.

(Incidentally, I wasn't sure in these examples whether to inherit from BaseModel in child classes or not.)

Is there some way I can constrain the Pydantic model to give me the interface behaviour that I need, throwing errors when a field is introduced that is not included in the ABC PersonEntity class?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source