[EMAIL PROTECTED] wrote:

> Thanks for all the help guys ... in almost every way using a metaclass
> seems to be the right solution for what I'm trying to do here.  I say
> almost because there is one thing that is still confusing me: what is
> the most elegant way to provide base-class implementations of methods
> that are expected to be overriden by some of the derived classes (or in
> the case of metaclasses, the classes that either declare __metaclass__
> = Exposed or are derived from such classes).
> 
> Here's what I've just knocked out:

[snip example]

> The problem here is that the implementation of 'bar' inside
> Exposed.__init__ overrides the implementation of bar() in Process,
> which makes sense I guess seeing as Exposed.__init__() is called after
> the class has been initialised.  It's not a problem for
> getExposedMethods() seeing as it's not overriden by any derived
> classes.
> 
> So what is the accepted way of doing this?  Do I need two Exposed
> classes, one is the metaclass that handles all the static mapping
> stuff, and another provides base implementations of methods and is what
> is actually derived from? E.g.:

You define one base type with a custom metaclass and inherit from that. Your
example then becomes:

import sys

class ExposedType( type ):
    def __init__( cls, *args, **kw ):
        # Track marked exposed methods
        cls.s_exposedMethods = []
        for superclass in cls.__mro__:
            for name, meth in superclass.__dict__.items():
                if hasattr( meth, "exposed" ):
                    cls.s_exposedMethods.append( name )

class Exposed:
    __metaclass__ = ExposedType
    def getExposedMethods(self):
        return self.s_exposedMethods
    def bar(self):
        print "bar\n"
    @staticmethod
    def expose( f ):
        f.exposed = True
        return f

class Process( Exposed):
    @Exposed.expose
    def foo( self ):
        pass
    def bar( self ):
        print "BAR"


class BotProcess( Process ):
    @Exposed.expose
    def addBots( self ):
        pass

p = Process()
p.bar()

This prints "BAR" as expected.

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

Reply via email to