Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems with ABC/Interfaces using pydantic + Mixins pattern

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)?

like image 676
Tâmer Cuba Avatar asked Jun 28 '26 23:06

Tâmer Cuba


1 Answers

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
like image 131
Nicu Tofan Avatar answered Jul 01 '26 13:07

Nicu Tofan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!