summaryrefslogtreecommitdiffstats
path: root/Tools/demo/eiffel.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/demo/eiffel.py')
-rwxr-xr-xTools/demo/eiffel.py146
1 files changed, 0 insertions, 146 deletions
diff --git a/Tools/demo/eiffel.py b/Tools/demo/eiffel.py
deleted file mode 100755
index a76c232..0000000
--- a/Tools/demo/eiffel.py
+++ /dev/null
@@ -1,146 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-Support Eiffel-style preconditions and postconditions for functions.
-
-An example for Python metaclasses.
-"""
-
-import unittest
-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.items():
- 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[m] = 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)
- rv = func(self, *args, **kwargs)
- if post:
- post(self, rv, *args, **kwargs)
- return rv
-
- 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:
-
- 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=None):
- 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
-
-
-class Tests(unittest.TestCase):
-
- def testEiffelMetaClass1(self):
- self._test(EiffelMetaClass1)
-
- def testEiffelMetaClass2(self):
- self._test(EiffelMetaClass2)
-
- def _test(self, metaclass):
- class Eiffel(metaclass=metaclass):
- pass
-
- 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()
- self.assertEqual(t.m(1), 2)
- self.assertEqual(t.m2(1), 2)
- self.assertRaises(AssertionError, t.m2, 0)
-
- s = Sub()
- self.assertRaises(AssertionError, s.m2, 1)
- self.assertRaises(AssertionError, s.m2, 10)
- self.assertEqual(s.m2(5), 25)
-
-
-if __name__ == "__main__":
- unittest.main()