AndreaCensi / contracts

PyContracts is a Python package that allows to declare constraints on function parameters and return values. Contracts can be specified using Python3 annotations, or inside a docstring. PyContracts supports a basic type system, variables binding, arithmetic constraints, and has several specialized contracts and an extension API.
http://andreacensi.github.io/contracts/
Other
399 stars 61 forks source link

List of defined contracts failing oddly #13

Closed asharp closed 11 years ago

asharp commented 11 years ago

I'm attempting to match a list of a newly defined contract (using a function), however contracts.check is running the function with some odd arguments.

import contracts
import types

def cheese(tmp):
        print 'seeing value', tmp
        return False

contracts.check("list[int]", [1])
contracts.new_contract("cheese", cheese)
contracts.check("cheese|list[cheese]|None", [ZeroDivisionError])

When run it returns

seeing value [<type 'exceptions.ZeroDivisionError'>]
seeing value 1
Traceback (most recent call last):
  File "failtest.py", line 10, in <module>
  contracts.check("cheese|list[cheese]|None", [ZeroDivisionError])
  File "/var/envs/node/lib/python2.6/site-packages/contracts/main.py", line 422, in check
   raise e
contracts.interface.ContractNotRespected: Could not satisfy any of the 3 clauses in    cheese|list[cheese]|None.
 ---- Clause #1:   cheese
 | Value does not pass criteria of cheese() (module: __main__).
 | checking: function cheese()      for value: Instance of list: [<type 'exceptions.ZeroDivisionError'>]   
 | checking: cheese                 for value: Instance of list: [<type 'exceptions.ZeroDivisionError'>]   
 ---- Clause #2:   list[cheese]
 | Value does not pass criteria of cheese() (module: __main__).
 | checking: function cheese()      for value: Instance of int: 1                                          
 | checking: cheese                 for value: Instance of int: 1                                          
 | checking: list[cheese]           for value: Instance of list: [<type 'exceptions.ZeroDivisionError'>]   
 ---- Clause #3:   None
 | Value does not pass criteria of is_None() (module: contracts.library.miscellaneous_aliases).
 | checking: function is_None()      for value: Instance of list: [<type 'exceptions.ZeroDivisionError'>]   
 | checking: None                    for value: Instance of list: [<type 'exceptions.ZeroDivisionError'>]   
------- (end clauses) -------
checking: cheese|list[cheese]|None      for value: Instance of list: [<type 'exceptions.ZeroDivisionError'>]  

Which, is odd. Specificity i'm wondering why the contract handler for cheese gets run with "1" as an argument. I'm thinking that it might be because the parser is getting confused about it being a variable?

AndreaCensi commented 11 years ago

The syntax is: list[length](type), so cheese is being passed the length of the list, which is 1.

asharp commented 11 years ago

Ah. I'm an idiot. facepalm Thanks for that.