mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			120 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Generic metaclass.
 | |
| 
 | |
| XXX This is very much a work in progress.
 | |
| 
 | |
| """
 | |
| 
 | |
| import types
 | |
| 
 | |
| class MetaMethodWrapper:
 | |
| 
 | |
|     def __init__(self, func, inst):
 | |
|         self.func = func
 | |
|         self.inst = inst
 | |
|         self.__name__ = self.func.__name__
 | |
| 
 | |
|     def __call__(self, *args, **kw):
 | |
|         return apply(self.func, (self.inst,) + args, kw)
 | |
| 
 | |
| class MetaHelper:
 | |
| 
 | |
|     __methodwrapper__ = MetaMethodWrapper # For derived helpers to override
 | |
| 
 | |
|     def __helperinit__(self, formalclass):
 | |
|         self.__formalclass__ = formalclass
 | |
| 
 | |
|     def __getattr__(self, name):
 | |
|         # 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)
 | |
| 
 | |
| class MetaClass:
 | |
| 
 | |
|     """A generic metaclass.
 | |
| 
 | |
|     This can be subclassed to implement various kinds of meta-behavior.
 | |
| 
 | |
|     """
 | |
| 
 | |
|     __helper__ = MetaHelper             # For derived metaclasses to override
 | |
| 
 | |
|     __inited = 0
 | |
| 
 | |
|     def __init__(self, name, bases, dict):
 | |
|         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
 | |
| 
 | |
|     def __getattr__(self, name):
 | |
|         try:
 | |
|             return self.__realdict__[name]
 | |
|         except KeyError:
 | |
|             for base in self.__bases__:
 | |
|                 try:
 | |
|                     return base.__getattr__(name)
 | |
|                 except AttributeError:
 | |
|                     pass
 | |
|             raise AttributeError, name
 | |
| 
 | |
|     def __setattr__(self, name, value):
 | |
|         if not self.__inited:
 | |
|             self.__dict__[name] = value
 | |
|         else:
 | |
|             self.__realdict__[name] = value
 | |
| 
 | |
|     def __call__(self, *args, **kw):
 | |
|         inst = self.__helper__()
 | |
|         inst.__helperinit__(self)
 | |
|         try:
 | |
|             init = inst.__getattr__('__init__')
 | |
|         except AttributeError:
 | |
|             init = lambda: None
 | |
|         apply(init, args, kw)
 | |
|         return inst
 | |
|     
 | |
| 
 | |
| Meta = MetaClass('Meta', (), {})
 | |
| 
 | |
| 
 | |
| def _test():
 | |
|     class C(Meta):
 | |
|         def __init__(self, *args):
 | |
|             print "__init__, args =", args
 | |
|         def m1(self, x):
 | |
|             print "m1(x=%s)" %`x`
 | |
|     print C
 | |
|     x = C()
 | |
|     print x
 | |
|     x.m1(12)
 | |
|     class D(C):
 | |
|         def __getattr__(self, name):
 | |
|             if name[:2] == '__': raise AttributeError, name
 | |
|             return "getattr:%s" % name
 | |
|     x = D()
 | |
|     print x.foo
 | |
|     print x._foo
 | |
| ##     print x.__foo
 | |
| ##     print x.__foo__
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     _test()
 | |
| 
 | |
|     
 | 
