home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Demo / metaclasses / Meta.py < prev    next >
Text File  |  1997-08-25  |  2KB  |  121 lines

  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:
  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=%s)" %`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()
  119.  
  120.     
  121.