Turns out the first msg I sent did not reach the list, so I'll just post what I've achieved by now:
------------------------------------------
class DecoratorDummy(object): pass

class InheritedDecoratorType(type):
        def __new__(cls, name, bases, dct):
                # return if its a class which inherited from Decorator
                if Decorator in bases:
                        return type.__new__(cls, name, bases, {})
                
                # if its a class which did not directly inherit from Decorator,
                # then it inherited from a class which has been manipulated 
using the
                # Decorator class.
                # in that case we change the bases of the inheriting class.
                # We'll split the manipulated class into Decorator and its 
implementation
                for b in bases:
                        if type(b) is InheritedDecoratorType:
                                break
                newbases = [x for x in bases]
                # remove the manipulated base class
                newbases.remove(b)
                # and add the impl of the manipulated base class
                newbases.append(b._impl_type)
                # and add the Decorator class
                newbases.append(Decorator)
# now we'll have to make sure the dict of the new class shows the original base class
                # (which has been removed) as the implementation class
                dct[b.__name__] =  b._impl_type
                # since we have added a Decorator class, we ought to get rid of 
it
                # through the DecoratorType metaclass
                r = DecoratorType.__new__(cls, name, tuple(newbases), dct)
                
                return r

class DecoratorType(type):
        def __new__(cls, name, bases, dct):

                # if the first class is DecoratorDummy, then we're handling the
                # Decorator class, which is not supposed to be modified
                if bases[0] is DecoratorDummy:
                        return type.__new__(cls, name, bases, {})
                
                # if one of the bases is the Decorator class
                b = [x for x in bases]
                if Decorator in b:
# create a new impl type which inherits from every but the decorator class
                        b.remove(Decorator)
                        
                impl_type = type('%sImpl'%name, tuple(b), dict(dct))
# make the returned type no longer a DecoratorType, but rather a normal type # Types which inherit from a class which inherited from Decorator, will thus
                # *not* be put through this metaclass.
                #dectype = type.__new__(type, name, tuple(b), {'_impl_type' : 
impl_type })
dectype = type.__new__(InheritedDecoratorType, name, tuple(b), {'_impl_type' : impl_type })
                
                # update the old class to implement this implementation
                def __init__(self, *args, **dargs):
                        new_impl = impl_type(*args, **dargs)
                        super(dectype._impl_type, new_impl).__init__(*args,
                                                                                
                                         **dargs)
                        object.__setattr__(self, '_impl', new_impl)
                def decorator(self):
                        return object.__getattribute__(self, '_impl')
                def __getattribute__(self, attr):
                        if attr=="decorator":
                                return object.__getattribute__(self, 
'decorator')
                        
                        # if we have a specified method inside the 
decorator().__decorate__ var,
                        # then call decorator().attr(), otherwise proxy the call
                        d = object.__getattribute__(self, 'decorator')()
                        if attr in d.__decorate__:
                                return getattr(d, attr)
                        return getattr(d.getParent(), attr)
                dectype.__init__ = __init__
                dectype.decorator = decorator
                dectype.__getattribute__ = __getattribute__
                
                return dectype

class Decorator(DecoratorDummy):
                __metaclass__ = DecoratorType

class Window(object):
        def __init__(self, parent):
                print "Window::__init__(%s)"%self
                self._parent = parent
        
        def setParent(self, parent):
                self._parent = parent
        
        def getParent(self):
                return self._parent

class Textarea(Window):
        def draw(self):
                print "Textarea::draw()"

class HBar(Decorator, Window):
        __decorate__ = ["draw"]
        def __init__(self, parent):
                print "HBar::__init__(%s)"%self
                Window.__init__(self, parent=parent)
                
                self._progress = 0.0
                
        def setProgress(self, p):
                print "setting progress to %s"%p
                self._progress= p
                
        def getProgress(self):
                return self._progress
        
        def draw(self):
                self.getParent().draw()
                print "HBar::draw()"
                
class HBarTrue(HBar):
        # HBar's bases: Window (Decorator removed by metaclass)
        # HBar's methods: __init__, decorator, __getattribute__
        # everything else is inside decorator()
        # we thus need to make calls to self within HBarTrue,
        # calls to self.decorator() - this is not possible
        # Otherwise we could also let HBarTrue inherit from HBarImpl,
        # however then a call to HBar.__init__ would be invalid inside
        # HBarTrue.__init__ unless we specify HBar internally as being HBarImpl
        # - this however is not possible
        # if we inherit from HBarImpl, then we no longer have the decorator
        # functionality. We'd thus have to include Decorator in the list of 
bases
        
        # Inherit normally from HBar and not Decorator.
        # Move all methods from HBarTrue to HBar.decorator()
        # create a custom __init__ method which calls HBar.decorator().__init__
        
        def __init__(self, parent):
                print "HBarTrue::__init__(%s)"%self
                for each in dir(self):
                        print each
                HBar.__init__(self, parent)
                
                self.setProgress(0.0)

myTextarea = Textarea("main.parent")
myTextarea.draw()
myTextarea = HBarTrue(myTextarea)
myTextarea.draw()
myTextarea.decorator().setProgress(100.0)
------------------------------------------
The code above works only if I don't inherit from HBar like I did.
As it is now, the HBar class, which inherits from Decorator and Window, is going to be manipulated by the metaclass. During this process the Decorator base-class is removed, the implementation of HBar moved into _impl_type and the methods __init__, decorator and __getattribute__ are being assigned to the new class.
Everything works so far if I don't subclass HBar.
If I do subclass HBar, then the subclass goes through the second metaclass (InheritedDecoratorType). In there I replace the base class HBar with HBarImpl and Decorator. This way the subclass inherits the implementation of HBar and through the Decorator class then the subclass goes through the same metaclass magic as HBar in the first step. Of course however, since HBarTrue is no longer a subclass of HBar (since that baseclass has been removed), the HBar.__init__ method won't accept the non HBar self parameter.

Now the reason why I'm using decorators, is because I want to be ably to add the functionality dynamicly - without the need of construction classes for the different possibilities. Composite pattern does not help in this case, since I lose the ability to choose in what order I call the decorator's and the decorated's methods.

I'll just keep trying. Any input greatly appreciated.

Regards,
Thomas K.

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to