I have two base classes, Foo and Bar, and a Worker class which expects objects that behave like Foo. Then I add another class that implements all relevant attributes and methods from Foo but I didn't manage to communicate this successfully to static type checking via mypy. Here's a small example:
class MyMeta(type):
    pass
class Bar(metaclass=MyMeta):
    def bar(self):
        pass
class Foo:
    def __init__(self, x: int):
        self.x = x
    def foo(self):
        pass
class Worker:
    def __init__(self, obj: Foo):
        self.x = obj.x
Here Worker actually accepts any Foo-ish object, i.e. objects that have an attribute x and a method foo. So if obj walks like a Foo and if it quacks like a Foo then Worker will be happy. Now the whole project uses type hints and so for the moment I indicate obj: Foo. So far so good.
Now there's another class FooBar, which subclasses Bar and behaves like Foo but it can't subclass Foo because it exposes its attributes via properties (and so the __init__ parameters don't make sense):
class FooBar(Bar):
    """Objects of this type are bar and they are foo-ish."""
    @property
    def x(self) -> int:
        return 0
    def foo(self):
        pass
At this point, doing Worker(FooBar()) obviously results in a type checker error:
error: Argument 1 to "Worker" has incompatible type "FooBar"; expected "Foo"
Using an abstract base class
In order to communicate the interface of Foo-ish to the type checker I thought about creating an abstract base class for Foo-ish types:
import abc
class Fooish(abc.ABC):
    x : int
    @abc.abstractmethod
    def foo(self) -> int:
        raise NotImplementedError
However I can't make FooBar inherit from Fooish because Bar has its own metaclass and so this would cause a metaclass conflict. So I thought about using Fooish.register on both Foo and FooBar but mypy doesn't agree:
@Fooish.register
class Foo:
    ...
@Fooish.register
class FooBar(Bar):
    ...
class Worker:
    def __init__(self, obj: Fooish):
        self.x = obj.x
Which produces the following errors:
error: Argument 1 to "Worker" has incompatible type "Foo"; expected "Fooish"
error: Argument 1 to "Worker" has incompatible type "FooBar"; expected "Fooish"
Using a "normal" class as an interface
The next option I considered is creating an interface without inheriting from abc.ABC in form of a "normal" class and then have both Foo and FooBar inherit from it:
class Fooish:
    x : int
    def foo(self) -> int:
        raise NotImplementedError
class Foo(Fooish):
    ...
class FooBar(Bar, Fooish):
    ...
class Worker:
    def __init__(self, obj: Fooish):
        self.x = obj.x
Now mypy doesn't complain about the argument type to Worker.__init__ but it complains about signature incompatibility of FooBar.x (which is a property) with Fooish.x:
error: Signature of "x" incompatible with supertype "Fooish"
Also the Fooish (abstract) base class is now instantiable and a valid argument to Worker(...) though it doesn't make sense since it doesn't provide an attribute x.
The question ...
Now I'm stuck at the question on how to communicate this interface to the type checker without using inheritance (due to metaclass conflict; even if it was possible, mypy would still complain about signature incompatibility of x). Is there a way to do it?
 
     
    