import abc
class ConprehensiveABCMeta(abc.ABCMeta):
_NOTFOUND = object()
def __new__(metacls, name, bases, namespace, /, **kwargs):
cls = super().__new__(metacls, name, bases, namespace, **kwargs)
abstracts = set(cls.__abstractmethods__)
for name in cls.__abstractmethods__:
for base in bases:
value = getattr(base, name, cls._NOTFOUND)
if not (value is cls._NOTFOUND or
getattr(value, '__isabstractmethod__', False)):
setattr(cls, name, value)
abstracts.remove(name)
break
cls.__abstractmethods__ = frozenset(abstracts)
return cls
class ConprehensiveABC(metaclass=ConprehensiveABCMeta):
pass
class A(ConprehensiveABC):
@abc.abstractmethod
def x(self):
pass
def y(self):
return "A.y"
class B(ConprehensiveABC):
@abc.abstractmethod
def y(self):
pass
def x(self):
return "B.x"
class AB(B, A):
pass
ab = AB()
print(ab.x())
print(ab.y())
aW1wb3J0IGFiYwoKY2xhc3MgQ29ucHJlaGVuc2l2ZUFCQ01ldGEoYWJjLkFCQ01ldGEpOgogICAgX05PVEZPVU5EID0gb2JqZWN0KCkKCiAgICBkZWYgX19uZXdfXyhtZXRhY2xzLCBuYW1lLCBiYXNlcywgbmFtZXNwYWNlLCAvLCAqKmt3YXJncyk6CiAgICAgICAgY2xzID0gc3VwZXIoKS5fX25ld19fKG1ldGFjbHMsIG5hbWUsIGJhc2VzLCBuYW1lc3BhY2UsICoqa3dhcmdzKQogICAgICAgIGFic3RyYWN0cyA9IHNldChjbHMuX19hYnN0cmFjdG1ldGhvZHNfXykKICAgICAgICBmb3IgbmFtZSBpbiBjbHMuX19hYnN0cmFjdG1ldGhvZHNfXzoKICAgICAgICAgICAgZm9yIGJhc2UgaW4gYmFzZXM6CiAgICAgICAgICAgICAgICB2YWx1ZSA9IGdldGF0dHIoYmFzZSwgbmFtZSwgY2xzLl9OT1RGT1VORCkKICAgICAgICAgICAgICAgIGlmIG5vdCAodmFsdWUgaXMgY2xzLl9OT1RGT1VORCBvcgogICAgICAgICAgICAgICAgICAgICAgICBnZXRhdHRyKHZhbHVlLCAnX19pc2Fic3RyYWN0bWV0aG9kX18nLCBGYWxzZSkpOgogICAgICAgICAgICAgICAgICAgIHNldGF0dHIoY2xzLCBuYW1lLCB2YWx1ZSkKICAgICAgICAgICAgICAgICAgICBhYnN0cmFjdHMucmVtb3ZlKG5hbWUpCiAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICBjbHMuX19hYnN0cmFjdG1ldGhvZHNfXyA9IGZyb3plbnNldChhYnN0cmFjdHMpCiAgICAgICAgcmV0dXJuIGNscwoKY2xhc3MgQ29ucHJlaGVuc2l2ZUFCQyhtZXRhY2xhc3M9Q29ucHJlaGVuc2l2ZUFCQ01ldGEpOgogICAgcGFzcwoKY2xhc3MgQShDb25wcmVoZW5zaXZlQUJDKToKICAgIEBhYmMuYWJzdHJhY3RtZXRob2QKICAgIGRlZiB4KHNlbGYpOgogICAgICAgIHBhc3MKCiAgICBkZWYgeShzZWxmKToKICAgICAgICByZXR1cm4gIkEueSIKCgpjbGFzcyBCKENvbnByZWhlbnNpdmVBQkMpOgogICAgQGFiYy5hYnN0cmFjdG1ldGhvZAogICAgZGVmIHkoc2VsZik6CiAgICAgICAgcGFzcwoKICAgIGRlZiB4KHNlbGYpOgogICAgICAgIHJldHVybiAiQi54IgoKY2xhc3MgQUIoQiwgQSk6CiAgICBwYXNzCgoKYWIgPSBBQigpCnByaW50KGFiLngoKSkKcHJpbnQoYWIueSgpKQ==