customizing metaclass constructed classes

Robert Brewer fumanchu at amor.org
Tue Feb 15 12:42:58 EST 2005


Robin Becker wrote:
> I have a set of classes for database access which are 
> constructed using a 
> special metaclass and base class.
> 
> so in the base module
> 
> #base.py
> class M(type):
>     def __init__(cls, name, bases, dict):
>        super(M, cls).__init__(name, bases, dict)
>        for f in dict['_fieldDefs']:
>            #create special property based on the field def
>            ....
> 
> class A(object):
>     __metaclass__ = M
>     _fieldDefs = []
> 
>     #base methods
>     ......
> 
> in the database module we use the above
> eg
> 
> #database.py
> class C(A):
>    _fieldDefs =[
>      IntColumn('id',primaryKey=1,allowNull=0),
>      TextColumn('name',allowNull=0,size=50),
>      TextColumn('description',allowNull=1,size=50),
>      ]
> 
> Now to my question: can I change the definition of the client 
> class C at run 
> time? I want to do something like add another element to C's 
> _fieldDefs and then 
> get it to go through the construction phase provided by M. 
> It's clearly 
> pointless for me to try something like
> 
> from database import C
> C._fieldDefs.append(....)
> 
> as C is constructed by the import.
> I either have to delay C's construction or reconstruct it.
> 
> Would something like this do?
> 
> def reconstruct():
>      import database
>      class C(database.C):
>        _fieldDefs = database.C._fieldDefs+[......]
>      database.C = C
> 
> Is there a better way to do this which preserves more of C's 
> original identity? 
> I suppose I want to call the metaclass initialization again, 
> but can't see a way to do that.

You *are* using a language with callable functions, right? ;)

#base.py

def create_special_property(cls, f):
   # create special property based on f

class M(type):
    def __init__(cls, name, bases, dict):
       super(M, cls).__init__(name, bases, dict)
       for f in dict['_fieldDefs']:
           create_special_property(cls, f)

#database.py
class C(A):
   _fieldDefs =[
     IntColumn('id',primaryKey=1,allowNull=0),
     TextColumn('name',allowNull=0,size=50),
     TextColumn('description',allowNull=1,size=50),
     ]

base.create_special_property(C, DateColumn('start_date'))

Slightly off-topic: if you really want to make it pretty, add a custom
descriptor so you can write:

class C(A):
   id = IntColumn(primaryKey=1,allowNull=0)
   name = TextColumn(allowNull=0,size=50)
   description = TextColumn(allowNull=1,size=50)

See UnitProperty (the descriptor), MetaUnit (the metaclass), and Unit
(the domain object) in http://www.aminus.org/rbre/dejavu/__init__.py for
an implementation of mine which you can steal in toto (because it's
public domain).


Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org



More information about the Python-list mailing list