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()
|
---|