symbian-qemu-0.9.1-12/python-2.6.1/Demo/metaclasses/Meta.py
author Gareth Stockwell <gareth.stockwell@accenture.com>
Wed, 22 Sep 2010 15:40:40 +0100
branchgraphics-phase-3
changeset 111 345f1c88c950
parent 1 2fb8b9db1c86
permissions -rw-r--r--
Fixes to syborg-graphicswrapper.vcproj These changes allow syborg-graphicswrapper to link against the hostthreadadapter and khronosapiwrapper libraries built by the graphics.simulator component. The .vcproj file uses relative paths, which requires that the following three packages are laid out as follows: os/ graphics adapt/ graphics.simulator qemu

"""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, AttributeError):
                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=%r)" % (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()