[pypy-svn] r40934 - in pypy/dist: demo pypy/lib

afayolle at codespeak.net afayolle at codespeak.net
Wed Mar 21 15:09:31 CET 2007


Author: afayolle
Date: Wed Mar 21 15:09:30 2007
New Revision: 40934

Added:
   pypy/dist/demo/contract_stack.py   (contents, props changed)
   pypy/dist/demo/contracts.py   (contents, props changed)
   pypy/dist/pypy/lib/dbc.py   (contents, props changed)
Log:
simple design by contract module built on top of aop.py, and demo

Added: pypy/dist/demo/contract_stack.py
==============================================================================
--- (empty file)
+++ pypy/dist/demo/contract_stack.py	Wed Mar 21 15:09:30 2007
@@ -0,0 +1,50 @@
+
+class Stack:
+    """A very simple stack interface
+    (not very useful in Python)
+    """
+
+    def __init__(self, max_size = 10):
+        self.max_size = max_size
+        self.elements = []
+
+    def _pre_pop(self):
+        return not self.is_empty()
+    def _post_pop(self, old, ret):
+        return ret == old.top() and \
+               self.size() == old.size() - 1
+    def pop(self):
+        return self.elements.pop()
+
+
+    def _pre_push(self, obj):
+        return obj is not None and not self.is_full()
+    def _post_push(self, old, ret, obj):
+        return not self.is_empty() and (self.top() == obj)
+    def push(self, obj):
+        self.elements.append(obj)
+
+
+    def top(self):
+        """Returns the top element of the stack
+        """
+        return self.elements[-1]
+    
+    def is_empty(self):
+        """Tells whether or not the stack is empty
+        """
+        return not bool(self.elements)
+
+
+    def is_full(self):
+        """Tells whether or not the stack is full
+        """
+        return len(self.elements) == self.max_size
+    
+    def size(self):
+        """Returns the current size of the stack
+        """
+        return len(self.elements)
+
+    def __str__(self):
+        return "elements = %s, max_size = %s" % (self.elements, self.max_size)

Added: pypy/dist/demo/contracts.py
==============================================================================
--- (empty file)
+++ pypy/dist/demo/contracts.py	Wed Mar 21 15:09:30 2007
@@ -0,0 +1,41 @@
+from dbc import ContractAspect, ContractError
+ContractAspect()
+from  contract_stack import Stack
+
+def run():
+    """This is an example of how contracts work
+    """
+    print "*"*30
+    print "Creating an empty stack (max_size = 3)"
+    stack = Stack(3)
+
+    try:
+        print "Empty stack, pop() should fail"
+        stack.pop()
+    except ContractError, excpt:
+        print "\t failed with %s, (OK)" % excpt
+    else:
+        print "\t did not failed, (XXX)"
+
+    print "\n\n\n"
+    stack.push(1)
+    print "push 1 done"
+    stack.push(2)
+    print "push 2 done"
+    stack.push(3)
+    print "push 3 done"
+        
+    try:
+        print "The stack is full, push() should fail"
+        stack.push(4)
+    except ContractError, excpt:
+        print "\t failed with %s, (OK)" % excpt
+    else:
+        print "\t did not failed, (XXX)"
+
+    print "\n\n\n"
+
+
+
+if __name__ == '__main__':
+    run()

Added: pypy/dist/pypy/lib/dbc.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lib/dbc.py	Wed Mar 21 15:09:30 2007
@@ -0,0 +1,42 @@
+__all__ = ['ContractAspect', 'ContractError', 'PreconditionError', 'PostConditionError']
+from aop import *
+from copy import deepcopy
+class ContractAspect:
+    __metaclass__ = Aspect
+    def __init__(self):
+        self.initial_state = {}
+
+    @around(PointCut(func='[^_].*', klass='.+').execution())
+    def contract_check(self, tjp):
+        target = tjp.target()
+        args, kwargs = tjp.arguments()
+        try:
+            prefunc = getattr(target, '_pre_%s' % tjp.name())
+        except AttributeError:
+            prefunc = None
+        try:
+            postfunc = getattr(target, '_post_%s' % tjp.name())
+        except AttributeError:
+            postfunc = None
+        else:
+            oldtarget = deepcopy(target)
+                    
+        if prefunc is not None:
+            status = prefunc(*args, **kwargs)
+            if not status:
+                raise PreconditionError(tjp.name())
+        tjp.proceed(target, *args, **kwargs)
+        if postfunc is not None:
+            if not postfunc(oldtarget, tjp.result(), *args, **kwargs):
+                raise PostconditionError(tjp.name())
+        return tjp.result()
+                               
+    
+class ContractError(StandardError):
+    pass
+
+class PreconditionError(ContractError):
+    pass
+
+class PostconditionError(ContractError):
+    pass



More information about the Pypy-commit mailing list