1"""Generic metaclass. 2 3XXX This is very much a work in progress. 4 5""" 6 7import types 8 9class MetaMethodWrapper: 10 11 def __init__(self, func, inst): 12 self.func = func 13 self.inst = inst 14 self.__name__ = self.func.__name__ 15 16 def __call__(self, *args, **kw): 17 return apply(self.func, (self.inst,) + args, kw) 18 19class MetaHelper: 20 21 __methodwrapper__ = MetaMethodWrapper # For derived helpers to override 22 23 def __helperinit__(self, formalclass): 24 self.__formalclass__ = formalclass 25 26 def __getattr__(self, name): 27 # Invoked for any attr not in the instance's __dict__ 28 try: 29 raw = self.__formalclass__.__getattr__(name) 30 except AttributeError: 31 try: 32 ga = self.__formalclass__.__getattr__('__usergetattr__') 33 except (KeyError, AttributeError): 34 raise AttributeError, name 35 return ga(self, name) 36 if type(raw) != types.FunctionType: 37 return raw 38 return self.__methodwrapper__(raw, self) 39 40class MetaClass: 41 42 """A generic metaclass. 43 44 This can be subclassed to implement various kinds of meta-behavior. 45 46 """ 47 48 __helper__ = MetaHelper # For derived metaclasses to override 49 50 __inited = 0 51 52 def __init__(self, name, bases, dict): 53 try: 54 ga = dict['__getattr__'] 55 except KeyError: 56 pass 57 else: 58 dict['__usergetattr__'] = ga 59 del dict['__getattr__'] 60 self.__name__ = name 61 self.__bases__ = bases 62 self.__realdict__ = dict 63 self.__inited = 1 64 65 def __getattr__(self, name): 66 try: 67 return self.__realdict__[name] 68 except KeyError: 69 for base in self.__bases__: 70 try: 71 return base.__getattr__(name) 72 except AttributeError: 73 pass 74 raise AttributeError, name 75 76 def __setattr__(self, name, value): 77 if not self.__inited: 78 self.__dict__[name] = value 79 else: 80 self.__realdict__[name] = value 81 82 def __call__(self, *args, **kw): 83 inst = self.__helper__() 84 inst.__helperinit__(self) 85 try: 86 init = inst.__getattr__('__init__') 87 except AttributeError: 88 init = lambda: None 89 apply(init, args, kw) 90 return inst 91 92 93Meta = MetaClass('Meta', (), {}) 94 95 96def _test(): 97 class C(Meta): 98 def __init__(self, *args): 99 print "__init__, args =", args 100 def m1(self, x): 101 print "m1(x=%r)" % (x,) 102 print C 103 x = C() 104 print x 105 x.m1(12) 106 class D(C): 107 def __getattr__(self, name): 108 if name[:2] == '__': raise AttributeError, name 109 return "getattr:%s" % name 110 x = D() 111 print x.foo 112 print x._foo 113## print x.__foo 114## print x.__foo__ 115 116 117if __name__ == '__main__': 118 _test() 119