symbian-qemu-0.9.1-12/python-2.6.1/Demo/newmetaclasses/Eiffel.py
changeset 1 2fb8b9db1c86
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/python-2.6.1/Demo/newmetaclasses/Eiffel.py	Fri Jul 31 15:01:17 2009 +0100
@@ -0,0 +1,141 @@
+"""Support Eiffel-style preconditions and postconditions."""
+
+from types import FunctionType as function
+
+class EiffelBaseMetaClass(type):
+
+    def __new__(meta, name, bases, dict):
+        meta.convert_methods(dict)
+        return super(EiffelBaseMetaClass, meta).__new__(meta, name, bases,
+                                                        dict)
+
+    @classmethod
+    def convert_methods(cls, dict):
+        """Replace functions in dict with EiffelMethod wrappers.
+
+        The dict is modified in place.
+
+        If a method ends in _pre or _post, it is removed from the dict
+        regardless of whether there is a corresponding method.
+        """
+        # find methods with pre or post conditions
+        methods = []
+        for k, v in dict.iteritems():
+            if k.endswith('_pre') or k.endswith('_post'):
+                assert isinstance(v, function)
+            elif isinstance(v, function):
+                methods.append(k)
+        for m in methods:
+            pre = dict.get("%s_pre" % m)
+            post = dict.get("%s_post" % m)
+            if pre or post:
+                dict[k] = cls.make_eiffel_method(dict[m], pre, post)
+
+class EiffelMetaClass1(EiffelBaseMetaClass):
+    # an implementation of the "eiffel" meta class that uses nested functions
+
+    @staticmethod
+    def make_eiffel_method(func, pre, post):
+        def method(self, *args, **kwargs):
+            if pre:
+                pre(self, *args, **kwargs)
+            x = func(self, *args, **kwargs)
+            if post:
+                post(self, x, *args, **kwargs)
+            return x
+
+        if func.__doc__:
+            method.__doc__ = func.__doc__
+
+        return method
+
+class EiffelMethodWrapper:
+
+    def __init__(self, inst, descr):
+        self._inst = inst
+        self._descr = descr
+
+    def __call__(self, *args, **kwargs):
+        return self._descr.callmethod(self._inst, args, kwargs)
+
+class EiffelDescriptor(object):
+
+    def __init__(self, func, pre, post):
+        self._func = func
+        self._pre = pre
+        self._post = post
+
+        self.__name__ = func.__name__
+        self.__doc__ = func.__doc__
+
+    def __get__(self, obj, cls):
+        return EiffelMethodWrapper(obj, self)
+
+    def callmethod(self, inst, args, kwargs):
+        if self._pre:
+            self._pre(inst, *args, **kwargs)
+        x = self._func(inst, *args, **kwargs)
+        if self._post:
+            self._post(inst, x, *args, **kwargs)
+        return x
+
+class EiffelMetaClass2(EiffelBaseMetaClass):
+    # an implementation of the "eiffel" meta class that uses descriptors
+
+    make_eiffel_method = EiffelDescriptor
+
+def _test(metaclass):
+    class Eiffel:
+        __metaclass__ = metaclass
+
+    class Test(Eiffel):
+
+        def m(self, arg):
+            """Make it a little larger"""
+            return arg + 1
+
+        def m2(self, arg):
+            """Make it a little larger"""
+            return arg + 1
+
+        def m2_pre(self, arg):
+            assert arg > 0
+
+        def m2_post(self, result, arg):
+            assert result > arg
+
+    class Sub(Test):
+        def m2(self, arg):
+            return arg**2
+        def m2_post(self, Result, arg):
+            super(Sub, self).m2_post(Result, arg)
+            assert Result < 100
+
+    t = Test()
+    t.m(1)
+    t.m2(1)
+    try:
+        t.m2(0)
+    except AssertionError:
+        pass
+    else:
+        assert False
+
+    s = Sub()
+    try:
+        s.m2(1)
+    except AssertionError:
+        pass # result == arg
+    else:
+        assert False
+    try:
+        s.m2(10)
+    except AssertionError:
+        pass # result ==  100
+    else:
+        assert False
+    s.m2(5)
+
+if __name__ == "__main__":
+    _test(EiffelMetaClass1)
+    _test(EiffelMetaClass2)