Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python @precondition / @postcondition for member function - how?

I'm trying to use the @postcondition decorator on the value returned by a member function of a class, like this :

def out_gt0(retval, inval):
    assert retval > 0, "Return value < 0"

class foo(object):
    def __init__(self, w, h):
        self.width = w
        self.height = h
    @postcondition(out_gt0)
    def bar(self):
        return -1

When I try to call the member function 'bar' (and so provoke the @postcondition into providing a warning) I get this :

>>> f = foo(2,3)
>>> f.bar()
Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    f.bar()
  File "<pyshell#8>", line 106, in __call__
    result = self._func(*args, **kwargs)
TypeError: bar() takes exactly 1 argument (0 given)
>>> 

My definition of @postcondition is the one seen here http://wiki.python.org/moin/PythonDecoratorLibrary#Pre-.2FPost-Conditions.

I assume the error arises because the function that underlies @postcondition is not expecting to deal with a member function (certainly all the examples I've ever seen are just using plain old functions) but I'm not sure how to fix it so I can do this ?

Would be grateful for any advice.

like image 952
glaucon Avatar asked Aug 28 '12 00:08

glaucon


People also ask

What are precondition for function in Python?

A precondition is something that must be true at the start of a function in order for it to work correctly. A postcondition is something that the function guarantees is true when it finishes. An invariant is something that is always true at a particular point inside a piece of code.

How do you write pre and post conditions?

Pre-conditions are the things that must be true before a method is called. The method tells clients "this is what I expect from you". Post-conditions are the things that must be true after the method is complete. The method tells clients "this is what I promise to do for you".

What is precondition and postcondition in Python?

• Precondition – a condition that must be true before a function (or code segment) executes, in order. for the code to work correctly. • Postcondition - a condition that will be true after a functions returns or at the end of a code segment.

What is postcondition violation in Python?

What is postcondition violation in Python? There is something wrong with the arguments the function is getting; a precondition is violated. There is something wrong with the function; a postcondition is violated. There is something wrong with the return value or the way it is being used.30-Sept-2020.


1 Answers

You don't need to do anything special:

import functools

def condition(pre_condition=None, post_condition=None):
    def decorator(func):
        @functools.wraps(func) # presever name, docstring, etc
        def wrapper(*args, **kwargs): #NOTE: no self
            if pre_condition is not None:
               assert pre_condition(*args, **kwargs)
            retval = func(*args, **kwargs) # call original function or method
            if post_condition is not None:
               assert post_condition(retval)
            return retval
        return wrapper
    return decorator

def pre_condition(check):
    return condition(pre_condition=check)

def post_condition(check):
    return condition(post_condition=check)

Usage:

@pre_condition(lambda arg: arg > 0)
def function(arg): # ordinary function
    pass

class C(object):
    @post_condition(lambda ret: ret > 0)
    def method_fail(self):
        return 0
    @post_condition(lambda ret: ret > 0)
    def method_success(self):
        return 1

Test:

function(1)
try: function(0)
except AssertionError: pass
else: assert 0, "never happens"

c = C()
c.method_success()
try: c.method_fail()
except AssertionError: pass
else: assert 0, "never happens"
like image 160
jfs Avatar answered Nov 14 '22 23:11

jfs