First common ancestor

pythonic_fp.gadgets.first_common_ancestor(cls1: type, cls2: type) → type

First common ancestor

Best effort to find the least upper bound in the inheritance graph of two classes.

param cls1:

A class in the inheritance hierarchy.

param cls2:

A class in the inheritance hierarchy.

returns:

First common ancestor in cls1.__mro__ order.

raises TypeError:

Defensively raised when no common ancestor is found.

Note

The function is not symmetric in its arguments. In genuine multiple inheritance graphs, swapping cls1 and cls2 can yield a different ancestor. Also, a virtual ancestor registered with an ABC may be a tighter bound than anything in the actual MRO.

Note

Since object terminates all actual MRO’s, TypeError is unlikely to ever be thrown, except in the case of some exotic metaclass breaking this assumption. This exception is here mainly to let typing tools know that object None is not a possible return type.