| 1 | """Generic metaclass.
|
|---|
| 2 |
|
|---|
| 3 | XXX This is very much a work in progress.
|
|---|
| 4 |
|
|---|
| 5 | """
|
|---|
| 6 |
|
|---|
| 7 | import types
|
|---|
| 8 |
|
|---|
| 9 | class 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 |
|
|---|
| 19 | class 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 |
|
|---|
| 40 | class 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 |
|
|---|
| 93 | Meta = MetaClass('Meta', (), {})
|
|---|
| 94 |
|
|---|
| 95 |
|
|---|
| 96 | def _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 |
|
|---|
| 117 | if __name__ == '__main__':
|
|---|
| 118 | _test()
|
|---|