These files are a subset of the python-2.7.2.tgz distribution from python.org. Changed files from PyMod-2.7.2 have been copied into the corresponding directories of this tree, replacing the original files in the distribution. Signed-off-by: daryl.mcdaniel@intel.com git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13197 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			142 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""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)
 |