Different behaviour when using 2 contract notations
Opened this issue · 1 comments
jcrmatos commented
Hello,
I'm just trying out pycontracts and found this strange behavior when using different contract notations.
I import my module and run the function with an invalid argument and the contract's checks work fine when using this notation:
square_size = 9 # type: int
nr_rows = square_size # type: int
nr_cols = square_size # type: int
@contract(row_nr='int, >= 0, < $nr_rows', col_nr='int, >= 0, < $nr_cols',
returns='int,>= 0, < $square_size')
def loc2square_nr(row_nr, col_nr):
# type: (int, int) -> int
"""Convert location (row, column) to square number.
(int, int) -> int
:param row_nr: Row number to convert to square number.
:param col_nr: Column number to convert to square number.
:return: Square number.
"""
square_nr = (int(row_nr / square_side) * square_side
+ int(col_nr / square_side)) # type: int
return square_nr
But if I change the contract notation to inside the docstring, like this:
square_size = 9 # type: int
nr_rows = square_size # type: int
nr_cols = square_size # type: int
@contract
def loc2square_nr(row_nr, col_nr):
# type: (int, int) -> int
"""Convert location (row, column) to square number.
:param row_nr: Row number to convert to square number.
:type row_nr: int, >= 0, < $nr_rows
:param col_nr: Column number to convert to square number.
:type col_nr: int, >= 0, < $nr_cols
:return: Square number.
:rtype: int, >= 0, < $square_size
"""
square_nr = (int(row_nr / square_side) * square_side
+ int(col_nr / square_side)) # type: int
return square_nr
Python returns a huge error when importing the module (I called it base.py).
This is the final part of the error:
value = self._parseNoCache(instring, loc, doActions, callPreParse)
File "C:\Users\JMatos\Envs\solve_sudoku\lib\site-packages\pyparsing.py", line
1405, in _parseNoCache
tokens = fn( instring, tokensStart, retTokens )
File "C:\Users\JMatos\Envs\solve_sudoku\lib\site-packages\pyparsing.py", line
1049, in wrapper
ret = func(*args[limit[0]:])
File "C:\Users\JMatos\Envs\solve_sudoku\lib\site-packages\contracts\utils.py",
line 247, in f2
return f(*args, **kwargs)
File "C:\Users\JMatos\Envs\solve_sudoku\lib\site-packages\contracts\library\sc
oped_variables.py", line 95, in scoped_parse_action
val = _lookup_from_calling_scope(tokens[0])
File "C:\Users\JMatos\Envs\solve_sudoku\lib\site-packages\contracts\library\sc
oped_variables.py", line 67, in _lookup_from_calling_scope
raise ExternalScopedVariableNotFound(token)
contracts.interface.ExternalScopedVariableNotFound: Token not found: 'square_siz
e'.
>>>
If I understand correctly, pycontracts doesn't recognize the variable square_size in the 2nd notation. But it does on the 1st.
I'm using Python 32b 3.5.4 with pycontracts 1.8.3. I'm running on a Windows 7 Pro x64 PC.
Thanks,
JM
AndreaCensi commented
Thanks for the report @jcrmatos - this is a bug.