Search code examples
pythonpython-typingmixins

Main class typing in Python mixins


I have a class split into mixins:

class MyObject(MyObjectFilesMixin, MyObjectProcessingMixin, ...):
    def __init__(self, value):
        self.value = self.preprocess(value)

A mixin looks like this:

class MyObjectFilesMixin:
    def load_from_file(cls, filename):
        return ...

Now I'd like to add typing to the class and mixins:

class MyObjectFilesMixin:
    def load_from_file(cls, filename: str) -> MyObject:
        return ...


class MyObjectProcessingMixin:
    def preprocess(self: MyObject, value: bytes):
        return value  # logic is omitted

    def append(self: MyObject, other: MyObject):
        self.value += other.value

But it leads to cyclic links. Of course I can create some MyObjectBase (following dependency inversion principle), so that MyObject will also inherit this class, and mixins will use it as argument/return type, but this will lead to wrong types anyway. Is it possible to fix??

I miss so much header+source files from C++


Solution

  • I found how to do the trick without protocols or other unnecessary code, DRY! My solution is simple:

    from typing import TYPE_CHECKING, Type
    if TYPE_CHECKING:
        from my_object import MyObject
    MO = Type('MyObject')
    
    
    class MyObjectFilesMixin:
        def load_from_file(cls: MO, filename: str) -> 'MyObject':
            # Now I'm able to access all the methods of MyObject by cls
            # with correct IDE support and MyPy checking
            return ...
    
    
    class MyObjectProcessingMixin:
        def preprocess(self: 'MyObject', value: bytes):
            return value  # logic is omitted
    
        def append(self: 'MyObject', other: 'MyObject'):
            self.value += other.value
    

    However, I get another warning, probably because MyPy doesn't expect a child to be used as a type in parent:

    Mypy: The erased type of self "Type[... MyObject]" is not a supertype of its class "Type[...MyObjectFilesMixin]"

    But it's a little cost for the methods and types to be seen and understood correctly by IDE and MyPy!