class SuperWrapper(object):
"""Make sure descriptor super(cls) is invoked
even when called on a class."""
def __init__(self, cls):
self.cls = cls
def __get__(self, obj, cls):
if obj is None:
return super(self.cls, cls)
else:
return super(self.cls, obj)
class SuperMeta(type):
"Automatically add attribute __sup for every class."
def __init__(cls, name, bases, clsdict):
setattr(cls, '_{}__sup'.format(name), SuperWrapper(cls))
super(SuperMeta, cls).__init__(name, bases, clsdict)
# Usage examples:
class A(object):
__metaclass__ = SuperMeta
def meth(self):
print 'A.meth(%s)' % self
@classmethod
def clsmeth(cls):
print 'A.clsmeth(%s)' % cls
class B(A):
def meth(self):
self.__sup.meth() # super().meth()
print 'B.meth(%s)' % self
@classmethod
def clsmeth(cls):
cls.__sup.clsmeth() # super().clsmeth()
print 'B.clsmeth(%s)' % cls
class C(A):
def meth(self):
self.__sup.meth()
print 'C.meth(%s)' % self
@classmethod
def clsmeth(cls):
cls.__sup.clsmeth()
print 'C.clsmeth(%s)' % cls
class D(B, C):
def meth(self):
self.__sup.meth()
print 'D.meth(%s)' % self
@classmethod
def clsmeth(cls):
cls.__sup.clsmeth()
print 'D.clsmeth(%s)' % cls
d = D()
d.meth()
d.clsmeth()