Package medite :: Package MediteAppli :: Package test :: Module contract
[hide private]
[frames] | no frames]

Module contract

source code

Programming-by-contract for Python, based on Eiffel's DBC.

Programming by contract documents class and modules with invariants, expressions that must be true during the lifetime of a module or instance; and documents functions and methods with pre- and post- conditions that must be true during entry and return.

Copyright (c) 2003, Terence Way This module is free software, and you may redistribute it and/or modify it under the same terms as Python itself, so long as this copyright message and disclaimer are retained in their original form.

IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.


Version: 1.1: October 19, 2005

Author: Terence Way

Classes [hide private]
  Done
  tokenizer
  ContractViolationError
  PreconditionViolationError
  PostconditionViolationError
  InvariantViolationError
  InvalidPreconditionError
Method pre-conditions can only weaken overridden methods' preconditions.
  _holder
Placeholder for arbitrary 'old' values.
Functions [hide private]
 
checkmod(module, checklevel=0)
Add invariant, pre- and post-condition checking to a module.
source code
 
_check_type(code, path, checklevel)
Modify a class to add invariant checking.
source code
 
_check_proc(code, path, checklevel)
Modify a module or class to add invariant checking.
source code
 
_get_location(f)
Get function location as tuple (name, filename, lineno).
source code
 
_get_members(obj, path)
Returns two lists (procs, types) where each list contains (name, value) tuples.
source code
 
_check_members((procs, types), path, checklevel) source code
 
_ispublic(name)
Checks if a name is public (starts and ends with '__' or doesn't start with a _ at all).
source code
 
parse_docstring(docstring, keywords)
Parse a docstring, looking for design-by-contract expressions.
source code
 
_read_block(input, startlineno)
Read an indented block of expressions
source code
 
_install_wrapper(code, contracts, path, is_public, checklevel)
Creates and installs a function/method checker.
source code
 
isclass(obj) source code
 
isstring(obj) source code
 
_define_checker(name, args, contract, path)
Define a function that does contract assertion checking.
source code
 
_define_saver(name, args, decls, module)
Create a function that saves values into an __old__ variable.
source code
 
_define(name, text, module) source code
 
_format_args((arguments, rest, keywords, default_values))
Formats an argument desc into a string suitable for both a function/ method declaration or a function call.
source code
 
_format_arg(a)
Convert an argument list into a tuple string.
source code
 
_getargs(function) source code
 
_searchbases(cls, accum) source code
 
getargspec(function)
Get argument information about a function.
source code
 
_mkname(path, *va)
Define a name combining a path and arbitrary strings.
source code
 
_save_decls(output, name, d)
Recursively output a dictionary into a set of 'old' assignments.
source code
 
_decltodict(l)
Converts a list of list of names into a hierarchy of dictionaries.
source code
 
call_public_function_all(inv, func, *va, **ka)
Check the invocation of a public function or static method.
source code
 
call_public_function_pre(inv, func, *va, **ka)
Check the invocation of a public function or static method.
source code
 
call_private_function_all(func, *va, **ka)
Check the invocation of a private function or static method.
source code
 
call_private_function_pre(func, *va, **ka)
Check the invocation of a private function or static method.
source code
 
call_public_method_all(cls, method, *va, **ka)
Check the invocation of a public method.
source code
 
call_public_method_pre(cls, method, *va, **ka)
Check the invocation of a public method.
source code
 
call_constructor_all(cls, method, *va, **ka)
Check the invocation of an __init__ constructor.
source code
 
call_constructor_pre(cls, method, *va, **ka)
Check the invocation of an __init__ constructor.
source code
 
call_destructor_all(cls, method, *va, **ka)
Check the invocation of a __del__ destructor.
source code
 
call_destructor_pre(cls, method, *va, **ka)
Check the invocation of a __del__ destructor.
source code
 
call_private_method_all(cls, method, *va, **ka)
Check the invocation of a private method call.
source code
 
call_private_method_pre(cls, method, *va, **ka)
Check the invocation of a private method call.
source code
 
_check_class_invariants(mro, instance)
Checks class invariants on an instance.
source code
 
_method_call_all(mro, method, va, ka)
Check the invocation of a method.
source code
 
_method_call_pre(mro, method, va, ka)
Check the invocation of a method.
source code
 
_call_all(a, func, va, ka) source code
 
_call_pre(a, func, va, ka) source code
 
_check_preconditions(a, func, va, ka) source code
 
_has_method(cls, name)
Test if a class has a named method.
source code
 
__assert_inv()
Empty invariant assertions
source code
 
forall(a, fn=<type 'bool'>)
Checks that all elements in a sequence are true.
source code
 
exists(a, fn=<type 'bool'>)
Checks that at least one element in a sequence is true.
source code
 
implies(test, then_val, else_val=True)
Logical implication.
source code
Variables [hide private]
  __email__ = 'terry@wayforward.net'
  MODULE = 'contract'
  INV = 'inv'
  PRE = 'pre'
  POST = 'post'
  TYPE_CONTRACTS = ['inv']
  CODE_CONTRACTS = ['pre', 'post']
  OLD = '__old__'
  RETURN = '__return__'
  PREFIX = '__assert_'
  _ORIG = 'orig'
  _SAVE = 'save'
  _CHK = 'chk'
  _CONTRACTS = ('inv', 'pre', 'post')
  _re_start = re.compile(r'(?m)^\s*(inv|pre|post)\s*([\[:])')
  _RE_KEYWORD = 1
  _OPS = {',': 12, '.': 23, ':': 11, '[': 9, ']': 10}
  _EXCEPTIONS = {'inv': 'InvariantViolationError', 'post': 'Post...
  __test__ = {'_ispublic': _ispublic, '_get_members': _get_membe...
  CHECK_ALL = 3
  CHECK_DEFAULT = 0
  CHECK_NONE = 1
  CHECK_PRECONDITIONS = 2
  CO_VARARGS = 4
  CO_VARKEYWORDS = 8
  False = False
  True = True
Function Details [hide private]

checkmod(module, checklevel=0)

source code 

Add invariant, pre- and post-condition checking to a module.

pre:
   isstring(module) or isinstance(module, ModuleType)
   checklevel in [CHECK_DEFAULT, CHECK_NONE, CHECK_PRECONDITIONS,
                  CHECK_ALL]

_check_type(code, path, checklevel)

source code 

Modify a class to add invariant checking.

pre:
   isstring(code[0])
   type(code[1]) == code[2]
   isinstance(code[0], MethodType) or isinstance(code[0], FunctionType)
   isinstance(path[0], ModuleType)
   forall(path[1:], isclass)

_get_location(f)

source code 

Get function location as tuple (name, filename, lineno).

pre:
   isinstance(f, MethodType) or isinstance(f, FunctionType)
post[]:
   isstring(__return__[0])
   isstring(__return__[1])
   isinstance(__return__[2], int)

_get_members(obj, path)

source code 

Returns two lists (procs, types) where each list contains (name, value) tuples.

For classes, only attributes defined by the specific class are returned, i.e. not inherited attributes. Attributes created by this module (prefixed by '__assert_') are skipped as well.

Examples: >>> import contract >>> path = [contract] >>> hasattr(contract, '_re_start') 1 >>> '_re_start' in [x[0] for x in _get_members(contract, path)[0]] 0 >>> '_get_members' in [x[0] for x in _get_members(contract, path)[0]] 1 >>> 'checkmod' in [x[0] for x in _get_members(contract, path)[0]] 1 >>> class base: ... def foo(self): pass >>> class derived(base): ... def bar(self): pass

hasattr can get inherited attributes: >>> hasattr(derived, 'foo') 1

but we don't: >>> path = [__import__('__main__')] >>> 'foo' in [x[0] for x in _get_members(derived, path)[0]] 0

_ispublic(name)

source code 

Checks if a name is public (starts and ends with '__' or doesn't start with a _ at all).

Examples: >>> _ispublic('__init__') 1 >>> _ispublic('foo') 1 >>> _ispublic('_ispublic') 0

parse_docstring(docstring, keywords)

source code 
Parse a docstring, looking for design-by-contract expressions.

Returns a list of tuples: the list is the same length as keywords, and
matches each keyword.  The tuple is (keyword, [decls], [exprs]), namely
the keyword, a list of string declarations, and a list of tuples (string,
lineno).

Examples::
>>> from pprint import pprint
>>> pprint( parse_docstring(parse_docstring.__doc__, ['post', 'pre']) )
[('post', [], [('[ x [ 0 ] for x in __return__ ] == keywords', 22)]),
 ('pre',
  [],
  [('docstring is None or isstring ( docstring )', 18),
   ('forall ( keywords , isstring )', 19)])]

pre::
    docstring is None or isstring(docstring)
    forall(keywords, isstring)

post[]::
    [x[0] for x in __return__] == keywords

_read_block(input, startlineno)

source code 

Read an indented block of expressions

startlineno is *zero* origined line number.

pre:
   input.readline  # must have readline function

Examples: #>>> _read_block(StringIO('\tfoo:\n'), 0) #0 >>> _read_block(StringIO('\tpost[]: True\n'), 0) ('post', [], [('True', 1)], 1) >>> _read_block(StringIO('\tpre: 5 + 6 > 10\n'), 0) ('pre', [], [('5 + 6 > 10', 1)], 1) >>> _read_block(StringIO('\tpost:\n\t\t5 + 6 < 12\n\t\t2 + 2 == 4\n'), 0) ('post', [], [('5 + 6 < 12', 2), ('2 + 2 == 4', 3)], 3) >>> _read_block(StringIO('\tpost[foo.bar]: # changes\n' \ ... '\t\tlen(foo.bar) > 0\n'), 0) ('post', [['foo', 'bar']], [('len ( foo . bar ) > 0', 2)], 2)

Handles double colons (for re-structured text):: >>> _read_block(StringIO('\tpre:: 5 + 6 > 10\n'), 0) ('pre', [], [('5 + 6 > 10', 1)], 1)

_install_wrapper(code, contracts, path, is_public, checklevel)

source code 

Creates and installs a function/method checker.

pre:
   contracts[0][0] == PRE and contracts[1][0] == POST
   isinstance(path[0], ModuleType)
   forall(path[1:], isclass)

_define_checker(name, args, contract, path)

source code 

Define a function that does contract assertion checking.

args is a string argument declaration (ex: 'a, b, c = 1, *va, **ka') contract is an element of the contracts list returned by parse_docstring module is the containing module (not parent class)

Returns the newly-defined function.

pre:
   isstring(name)
   isstring(args)
   contract[0] in _CONTRACTS
   len(contract[2]) > 0
post:
   isinstance(__return__, FunctionType)
   __return__.__name__ == name

_define_saver(name, args, decls, module)

source code 

Create a function that saves values into an __old__ variable.

pre:: decls post:: isinstance(__return__, FunctionType)

_format_args((arguments, rest, keywords, default_values))

source code 

Formats an argument desc into a string suitable for both a function/ method declaration or a function call.

This does *not* handle default arguments. Default arguments are already evaluated... use new.function() to create a function with pre-evaluated default arguments.

Examples: >>> def foo(a, (b, c), d = 1, e = 2, *va, **ka): ... pass >>> a = getargspec(foo) >>> a (['a', '(b, c)', 'd', 'e'], 'va', 'ka', (1, 2)) >>> _format_args(a) 'a, (b, c), d, e, *va, **ka'

pre:
   isinstance(arguments, list)
   rest is None or isstring(rest)
   keywords is None or isstring(keywords)
post[]:: True

_format_arg(a)

source code 
Convert an argument list into a tuple string.
>>> _format_arg(['a', 'b', 'c'])
'(a, b, c)'
>>> _format_arg(['a', ['b', 'c', 'd']])
'(a, (b, c, d))'
>>> _format_arg(['a'])
'(a,)'
>>> _format_arg('a')
'a'

getargspec(function)

source code 

Get argument information about a function.

Returns a tuple (args, varargs, keywordvarargs, defaults) where args is a list of strings, varargs is None or the name of the *va argument, keywordvarargs is None or the name of the **ka argument, and defaults is a list of default values.

This function is different from the Python-provided inspect.getargspec in that 1) tuple arguments are returned as a string grouping '(a, b, c)' instead of broken out "['a', 'b', 'c']" and 2) it works in Jython, which doesn't support inspect (yet).
>>> getargspec(lambda a, b: a * b)
(['a', 'b'], None, None, None)
>>> getargspec(lambda a, (b, c, d) = (5, 6, 7), *va, **ka: a * b)
(['a', '(b, c, d)'], 'va', 'ka', ((5, 6, 7),))
pre:
   isinstance(function, FunctionType)
post[]:
   # tuple of form (args, va, ka, defaults)
   isinstance(__return__, TupleType) and len(__return__) == 4
   # args is a list of strings
   isinstance(__return__[0], ListType)
   forall(__return__[0], isstring)
   # va is None or a string
   __return__[1] is None or isstring(__return__[1])
   # ka is None or a string
   __return__[2] is None or isstring(__return__[2])
   # defaults is None or a tuple
   __return__[3] is None or isinstance(__return__[3], TupleType)

_mkname(path, *va)

source code 

Define a name combining a path and arbitrary strings.

pre:
  isinstance(path[0], ModuleType)
  forall(path[1:], isclass)
Examples: >>> import contract >>> _mkname([contract], 'test') '__assert_test' >>> class foo: ... pass >>> _mkname([contract, foo], 'func', 'pre') '__assert_foo_func_pre'

_save_decls(output, name, d)

source code 
Recursively output a dictionary into a set of 'old' assignments.

The dictionary d is a tree of variable declarations.  So, for example,
the declaration [self, self.buf, self.obj.a] would turn into the dict
{'self': {'buf': {}, 'obj': {'a': {}}}}, and would get output as
    __old__.self = contract._holder()
    __old__.self.buf = copy.copy(self.buf)
    __old__.self.obj = contract._holder()
    __old__.self.obj.a = copy.copy(self.obj.a)

_decltodict(l)

source code 

Converts a list of list of names into a hierarchy of dictionaries.

Examples: >>> d = _decltodict([['self', 'buf'], ... ['self', 'item', 'a'], ... ['self', 'item', 'b']]) >>> d == {'self': {'buf': {}, 'item': {'a': {}, 'b': {}}}} 1

call_public_function_all(inv, func, *va, **ka)

source code 

Check the invocation of a public function or static method.

Checks module invariants on entry and exit. Checks any pre-conditions and post-conditions.

call_public_function_pre(inv, func, *va, **ka)

source code 

Check the invocation of a public function or static method.

Checks module invariants on entry. Checks any pre-conditions.

call_private_function_all(func, *va, **ka)

source code 

Check the invocation of a private function or static method.

Only checks pre-conditions and post-conditions.

call_private_function_pre(func, *va, **ka)

source code 

Check the invocation of a private function or static method.

Only checks pre-conditions

call_public_method_all(cls, method, *va, **ka)

source code 

Check the invocation of a public method.

Check this class and all super-classes invariants on entry and exit. Checks all post-conditions of this method and all over- ridden method.

call_public_method_pre(cls, method, *va, **ka)

source code 

Check the invocation of a public method.

Check this class and all super-classes invariants on entry. exit.

call_constructor_all(cls, method, *va, **ka)

source code 

Check the invocation of an __init__ constructor.

Checks pre-conditions and post-conditions, and only checks invariants on successful completion.

call_constructor_pre(cls, method, *va, **ka)

source code 

Check the invocation of an __init__ constructor.

Checks pre-conditions and post-conditions, and only checks invariants on successful completion.

call_destructor_all(cls, method, *va, **ka)

source code 

Check the invocation of a __del__ destructor.

Checks pre-conditions and post-conditions, and only checks invariants on entry.

call_destructor_pre(cls, method, *va, **ka)

source code 

Check the invocation of a __del__ destructor.

Checks pre-conditions and post-conditions, and only checks invariants on entry.

call_private_method_all(cls, method, *va, **ka)

source code 

Check the invocation of a private method call.

Checks pre-conditions and post-conditions.

call_private_method_pre(cls, method, *va, **ka)

source code 

Check the invocation of a private method call.

Checks pre-conditions.

_check_class_invariants(mro, instance)

source code 

Checks class invariants on an instance.

mro - list of classes in method-resolution order instance - object to test

pre:
   # instance must be an instance of each class in mro
   forall(mro, lambda x: isinstance(instance, x))

_method_call_all(mro, method, va, ka)

source code 

Check the invocation of a method.

mro -- list/tuple of class objects in method resolution order

_method_call_pre(mro, method, va, ka)

source code 

Check the invocation of a method.

mro -- list/tuple of class objects in method resolution order

_has_method(cls, name)

source code 

Test if a class has a named method.

pre:
   isclass(cls)
   isstring(name)
post:: __return__ == (hasattr(cls, name) and isinstance(getattr(cls, name), MethodType))

forall(a, fn=<type 'bool'>)

source code 

Checks that all elements in a sequence are true.

Returns True(1) if all elements are true. Return False(0) otherwise.

Examples: >>> forall([True, True, True]) 1 >>> forall( () ) 1 >>> forall([True, True, False, True]) 0

exists(a, fn=<type 'bool'>)

source code 

Checks that at least one element in a sequence is true.

Returns True(1) if at least one element is true. Return False(0) otherwise.

Examples: >>> exists([False, False, True]) 1 >>> exists([]) 0 >>> exists([False, 0, '', []]) 0

implies(test, then_val, else_val=True)

source code 

Logical implication.

implies(x, y) should be read 'x implies y' or 'if x then y' implies(x, a, b) should be read 'if x then a else b'

Examples: >>> implies(False, False) 1 >>> implies(False, True) 1 >>> implies(True, False) 0 >>> implies(True, True) 1

Variables Details [hide private]

_EXCEPTIONS

Value:
{'inv': 'InvariantViolationError',
 'post': 'PostconditionViolationError',
 'pre': 'PreconditionViolationError'}

__test__

Value:
{'_ispublic': _ispublic, '_get_members': _get_members, '_decltodict': \
_decltodict, '_read_block': _read_block, '_format_args': _format_args,\
 '_mkname': _mkname}