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