| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  | """Generic metaclass.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | XXX This is very much a work in progress. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import types | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MetaMethodWrapper: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, func, inst): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         self.func = func | 
					
						
							|  |  |  |         self.inst = inst | 
					
						
							|  |  |  |         self.__name__ = self.func.__name__ | 
					
						
							| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __call__(self, *args, **kw): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         return apply(self.func, (self.inst,) + args, kw) | 
					
						
							| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class MetaHelper: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __methodwrapper__ = MetaMethodWrapper # For derived helpers to override | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __helperinit__(self, formalclass): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         self.__formalclass__ = formalclass | 
					
						
							| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __getattr__(self, name): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         # Invoked for any attr not in the instance's __dict__ | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             raw = self.__formalclass__.__getattr__(name) | 
					
						
							|  |  |  |         except AttributeError: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 ga = self.__formalclass__.__getattr__('__usergetattr__') | 
					
						
							|  |  |  |             except KeyError: | 
					
						
							|  |  |  |                 raise AttributeError, name | 
					
						
							|  |  |  |             return ga(self, name) | 
					
						
							|  |  |  |         if type(raw) != types.FunctionType: | 
					
						
							|  |  |  |             return raw | 
					
						
							|  |  |  |         return self.__methodwrapper__(raw, self) | 
					
						
							| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class MetaClass: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """A generic metaclass.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This can be subclassed to implement various kinds of meta-behavior. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |     __helper__ = MetaHelper             # For derived metaclasses to override | 
					
						
							| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     __inited = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, name, bases, dict): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             ga = dict['__getattr__'] | 
					
						
							|  |  |  |         except KeyError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             dict['__usergetattr__'] = ga | 
					
						
							|  |  |  |             del dict['__getattr__'] | 
					
						
							|  |  |  |         self.__name__ = name | 
					
						
							|  |  |  |         self.__bases__ = bases | 
					
						
							|  |  |  |         self.__realdict__ = dict | 
					
						
							|  |  |  |         self.__inited = 1 | 
					
						
							| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __getattr__(self, name): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             return self.__realdict__[name] | 
					
						
							|  |  |  |         except KeyError: | 
					
						
							|  |  |  |             for base in self.__bases__: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     return base.__getattr__(name) | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |             raise AttributeError, name | 
					
						
							| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __setattr__(self, name, value): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         if not self.__inited: | 
					
						
							|  |  |  |             self.__dict__[name] = value | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.__realdict__[name] = value | 
					
						
							| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __call__(self, *args, **kw): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         inst = self.__helper__() | 
					
						
							|  |  |  |         inst.__helperinit__(self) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             init = inst.__getattr__('__init__') | 
					
						
							|  |  |  |         except AttributeError: | 
					
						
							|  |  |  |             init = lambda: None | 
					
						
							|  |  |  |         apply(init, args, kw) | 
					
						
							|  |  |  |         return inst | 
					
						
							| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  |      | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Meta = MetaClass('Meta', (), {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _test(): | 
					
						
							|  |  |  |     class C(Meta): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         def __init__(self, *args): | 
					
						
							|  |  |  |             print "__init__, args =", args | 
					
						
							|  |  |  |         def m1(self, x): | 
					
						
							|  |  |  |             print "m1(x=%s)" %`x` | 
					
						
							| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  |     print C | 
					
						
							|  |  |  |     x = C() | 
					
						
							|  |  |  |     print x | 
					
						
							|  |  |  |     x.m1(12) | 
					
						
							| 
									
										
										
										
											1997-08-25 21:36:44 +00:00
										 |  |  |     class D(C): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         def __getattr__(self, name): | 
					
						
							|  |  |  |             if name[:2] == '__': raise AttributeError, name | 
					
						
							|  |  |  |             return "getattr:%s" % name | 
					
						
							| 
									
										
										
										
											1997-08-25 21:36:44 +00:00
										 |  |  |     x = D() | 
					
						
							|  |  |  |     print x.foo | 
					
						
							|  |  |  |     print x._foo | 
					
						
							|  |  |  | ##     print x.__foo | 
					
						
							|  |  |  | ##     print x.__foo__ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-08-25 15:37:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     _test() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      |