#7342: make sure that the datetime object in test_fraction always has a number of...
[python.git] / Demo / metaclasses / Meta.py
blob580f5821ce5df10c3f203172a9f1ca710bc60b86
1 """Generic metaclass.
3 XXX This is very much a work in progress.
5 """
7 import types
9 class MetaMethodWrapper:
11 def __init__(self, func, inst):
12 self.func = func
13 self.inst = inst
14 self.__name__ = self.func.__name__
16 def __call__(self, *args, **kw):
17 return apply(self.func, (self.inst,) + args, kw)
19 class MetaHelper:
21 __methodwrapper__ = MetaMethodWrapper # For derived helpers to override
23 def __helperinit__(self, formalclass):
24 self.__formalclass__ = formalclass
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)
40 class MetaClass:
42 """A generic metaclass.
44 This can be subclassed to implement various kinds of meta-behavior.
46 """
48 __helper__ = MetaHelper # For derived metaclasses to override
50 __inited = 0
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
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
76 def __setattr__(self, name, value):
77 if not self.__inited:
78 self.__dict__[name] = value
79 else:
80 self.__realdict__[name] = value
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
93 Meta = MetaClass('Meta', (), {})
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__
117 if __name__ == '__main__':
118 _test()