blob: b63f781c4a88cafdea1132c4d71a7f907c324438 [file] [log] [blame]
Guido van Rossum27e4aa31997-08-25 15:37:59 +00001"""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 _getattr_ = self.__dict__['_getattr_']
33 except KeyError:
34 raise AttributeError, name
35 return _getattr_(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 if dict.has_key('__getattr__'):
54 raise TypeError, "Can't override __getattr__; use _getattr_"
55 self.__name__ = name
56 self.__bases__ = bases
57 self.__realdict__ = dict
58 self.__inited = 1
59
60 def __getattr__(self, name):
61 try:
62 return self.__realdict__[name]
63 except KeyError:
64 for base in self.__bases__:
65 try:
66 return base.__getattr__(name)
67 except AttributeError:
68 pass
69 raise AttributeError, name
70
71 def __setattr__(self, name, value):
72 if not self.__inited:
73 self.__dict__[name] = value
74 else:
75 self.__realdict__[name] = value
76
77 def __call__(self, *args, **kw):
78 inst = self.__helper__()
79 inst.__helperinit__(self)
80 try:
81 init = inst.__getattr__('__init__')
82 except AttributeError:
83 init = lambda: None
84 apply(init, args, kw)
85 return inst
86
87
88Meta = MetaClass('Meta', (), {})
89
90
91def _test():
92 class C(Meta):
93 def __init__(self, *args):
94 print "__init__, args =", args
95 def m1(self, x):
96 print "m1(x=%s)" %`x`
97 print C
98 x = C()
99 print x
100 x.m1(12)
101
102
103if __name__ == '__main__':
104 _test()
105
106