Problems with ABC/Interfaces using pydantic + Mixins pattern
Asked Answered
H

1

8

Im trying to implement Mixin patter while Im using Pydantics BaseClass to facilitate the instantiation and validation of data from my class. The problem is that my Mixins cannot inhirit from my base classes (actually, the dependency is the opposite ). Also, im using mypy so my implementation needs to be rightly typed.

Lets see an simplified example:

class BaseCart(BaseModel):
    id: int
    items: List[Item]
    adress: str


class CartInterface(ABC):
    @abstractproperty
    def id(self):
        ...

    @abstractproperty
    def items(self):
        ...

    @abstractproperty
    def adress(self):
        ...

    @abstractmethod
    def get_shipping_value(self):
        ...

    @abstractmethod
    def get_items_availability(self):
        ...


class ShippingMixin(ABC, CartInterface):
    def get_shipping_value(self) -> int:
        # some business logic using self.address to calculate

class NormalItemsMixin(ABC, CartInterface):
    def get_items_availability(self) -> bool:
       # iterate over self.items and check stock availability

class AwesomeItemsMixin(ABC, CartInterface):
    def get_items_availability(self) -> bool:
       # iterate over self.items and check stock availability
       # this implementation is different from the normal one

class NormalCart(BaseCart, ShippingMixin, NormalItemsMixin):
    ...

class AwesomeCart(BaseCart, ShippingMixin, AwesomeItemsMixin):
    ...

The problem is that after implementing this, I can't instantiate AwesomeCart, I get the following error: TypeError: Can't instantiate abstract class ResellerCart with abstract methods business_unit, cart_type, channel, id, items, reseller, status, updated_at

What am I missing ?

TLDR: Why this


class Data(BaseModel):
    a: int

class IData(ABC):
    @abstractproperty
    def a(self):
        ...

class XData(Data, IData):
    ...

raises TypeError: Can't instantiate abstract class XData with abstract method a when I instanciates XData likes x = XData(a=1)?

Hardspun answered 15/7, 2021 at 16:57 Comment(1)
I have a similar problem, no one can help?Wichita
A
5

In IData a is only "masquarading" as a property when in fact it is a method of the class. You have to do something like

class Data(BaseModel):
    _a: int

    @property
    def a(self):
        return self._a


class IData(ABC):
    @abstractproperty
    def a(self):
        pass


class XData(Data, IData):
    pass

Now a in Data is also a method and the code works as expected.


@abstractproperty is deprecated since python 3.3, use 'property' with 'abstractmethod' instead.

class IData(ABC):
    @property
    @abstractmethod
    def a(self):
        pass
Adest answered 28/4, 2022 at 21:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.