Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/contracts/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '1.8.12'
__version__ = '1.8.13'

import logging

Expand Down
35 changes: 17 additions & 18 deletions src/contracts/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ class Where(object):

All parsed elements contain a reference to a :py:class:`Where` object
so that we can output pretty error messages.


Character should be >= len(string) (possibly outside the string).
Character_end should be >= character (so that you can splice with
Character_end should be >= character (so that you can splice with
string[character:character_end])
"""

Expand All @@ -38,7 +38,7 @@ def __init__(self, string, character, character_end=None):
# or (character <= character_end - 1)):
# character += 1
# else:
# break
# break
self.line, self.col = line_and_col(character, string)

if character_end is not None:
Expand Down Expand Up @@ -93,7 +93,7 @@ def __str__(self):
# mark = 'here or nearby'
def format_where(w, context_before=3, mark=None, arrow=True,
use_unicode=True, no_mark_arrow_if_longer_than=3):
s = u''
s = ''
if w.filename:
s += 'In file %r:\n' % w.filename
lines = w.string.split('\n')
Expand All @@ -108,7 +108,7 @@ def format_where(w, context_before=3, mark=None, arrow=True,
for i in range(start, w.line + 1):
# suppress empty lines
if one_written or lines[i].strip():
s += (u"%s%s\n" % (pattern % (i + 1), lines[i]))
s += ("%s%s\n".format(pattern % (i + 1), lines[i],))
one_written = True

fill = len(pattern % maxi)
Expand All @@ -119,29 +119,29 @@ def format_where(w, context_before=3, mark=None, arrow=True,
space_before = Where(w.string, char0, char0_end)

nindent = printable_length_where(space_before)
space = u' ' * fill + u' ' * nindent
space = ' ' * fill + ' ' * nindent
if w.col_end is not None:
if w.line == w.line_end:
num_highlight = printable_length_where(w)
s += space + u'~' * num_highlight + '\n'
space += u' ' * (num_highlight / 2)
s += space + '~' * num_highlight + '\n'
space += ' ' * (num_highlight / 2)
else:
# cannot highlight if on different lines
num_highlight = None
pass
else:
num_highlight = None
# Do not add the arrow and the mark if we have a long underline string
# Do not add the arrow and the mark if we have a long underline string

disable_mark_arrow = (num_highlight is not None) and (no_mark_arrow_if_longer_than < num_highlight)

if not disable_mark_arrow:
if arrow:
if use_unicode:
s += space + u'↑\n'
s += space + '↑\n'
else:
s += space + u'^\n'
s += space + u'|\n'
s += space + '^\n'
s += space + '|\n'

if mark is not None:
s += space + mark
Expand Down Expand Up @@ -173,7 +173,7 @@ def line_and_col(loc, strg):
from .utils import check_isinstance
check_isinstance(loc, int)
check_isinstance(strg, six.string_types)
# first find the line
# first find the line
lines = strg.split('\n')

if loc == len(strg):
Expand Down Expand Up @@ -433,8 +433,8 @@ def check_contract(self, context, value, silent): # @UnusedVariable
context. This is the function that subclasses must implement.

If silent = False, do not bother with creating detailed error messages yet.
This is for performance optimization.
This is for performance optimization.

:param context: The context in which expressions are evaluated.
:type context:
"""
Expand Down Expand Up @@ -548,7 +548,6 @@ def clipped_repr(x, clip):
s = "%s%s" % (s[:cut], clip_tag)
return s


# TODO: add checks for these functions


Expand Down Expand Up @@ -620,7 +619,7 @@ def describe_value_multiline(x):
try:
# This fails for classes
final = "{}\n{}".format(desc, x.__repr__())
except: # XXX
except: # XXX
final = "%s\n%s" % (desc, x)

return final
10 changes: 7 additions & 3 deletions src/contracts/library/map.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from ..interface import Contract, ContractNotRespected
from ..syntax import (W, contract_expression, O, S, add_contract, add_keyword,
Keyword)
import collections

try:
import collections.abc as collectionsAbc # python 3.6+
except ImportError:
import collections as collectionsAbc


class Map(Contract):
Expand All @@ -13,7 +17,7 @@ def __init__(self, length=None, key_c=None, value_c=None, where=None):
self.value_c = value_c

def check_contract(self, context, value, silent):
if not isinstance(value, collections.Mapping):
if not isinstance(value, collectionsAbc.Mapping):
error = 'Expected a Mapping, got %r.' % value.__class__.__name__
raise ContractNotRespected(contract=self, error=error,
value=value, context=context)
Expand Down Expand Up @@ -57,7 +61,7 @@ def parse_action(s, loc, tokens):

length_spec = S('[') - contract_expression('length') - S(']')
kv_spec = ('(' - O(contract_expression('key')) + ':'
+ O(contract_expression('value')) - ')')
+O(contract_expression('value')) - ')')
dict_contract = Keyword('map') + O(length_spec) + O(kv_spec)

dict_contract.setParseAction(Map.parse_action)
Expand Down
45 changes: 24 additions & 21 deletions src/contracts/library/miscellaneous_aliases.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,49 @@
import collections

try:
import collections.abc as collectionsAbc # python 3.6+
except ImportError:
import collections as collectionsAbc


def ist(C):

def f(x):
f.__name__ = 'isinstance_of_%s' % C.__name__
if not isinstance(x, C):
raise ValueError('Value is not an instance of %s.' % C.__name__)

return f


def m_new_contract(name, f):
from contracts.library.extensions import CheckCallable
from contracts.library.extensions import Extension
Extension.registrar[name] = CheckCallable(f)


m_new_contract('Container', ist(collections.Container))
# todo: Iterable(x)
m_new_contract('Iterable', ist(collections.Iterable))

m_new_contract('Hashable', ist(collections.Hashable))

m_new_contract('Container', ist(collectionsAbc.Container))
# todo: Iterable(x)
m_new_contract('Iterable', ist(collectionsAbc.Iterable))

m_new_contract('Hashable', ist(collectionsAbc.Hashable))

m_new_contract('Iterator', ist(collections.Iterator))
m_new_contract('Sized', ist(collections.Sized))
m_new_contract('Callable', ist(collections.Callable))
m_new_contract('Sequence', ist(collections.Sequence))
m_new_contract('Set', ist(collections.Set))
m_new_contract('MutableSequence', ist(collections.MutableSequence))
m_new_contract('MutableSet', ist(collections.MutableSet))
m_new_contract('Mapping', ist(collections.Mapping))
m_new_contract('MutableMapping', ist(collections.MutableMapping))
#new_contract('MappingView', ist(collections.MappingView))
#new_contract('ItemsView', ist(collections.ItemsView))
#new_contract('ValuesView', ist(collections.ValuesView))
m_new_contract('Iterator', ist(collectionsAbc.Iterator))
m_new_contract('Sized', ist(collectionsAbc.Sized))
m_new_contract('Callable', ist(collectionsAbc.Callable))
m_new_contract('Sequence', ist(collectionsAbc.Sequence))
m_new_contract('Set', ist(collectionsAbc.Set))
m_new_contract('MutableSequence', ist(collectionsAbc.MutableSequence))
m_new_contract('MutableSet', ist(collectionsAbc.MutableSet))
m_new_contract('Mapping', ist(collectionsAbc.Mapping))
m_new_contract('MutableMapping', ist(collectionsAbc.MutableMapping))
# new_contract('MappingView', ist(collections.MappingView))
# new_contract('ItemsView', ist(collections.ItemsView))
# new_contract('ValuesView', ist(collections.ValuesView))


# Not a lambda to have better messages
def is_None(x):
def is_None(x):
return x is None


m_new_contract('None', is_None)
m_new_contract('NoneType', is_None)
9 changes: 7 additions & 2 deletions src/contracts/library/seq.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
from ..interface import Contract, ContractNotRespected
from ..syntax import (add_contract, W, contract_expression, O, S, add_keyword,
Keyword)
import collections

try:
import collections.abc as collectionsAbc # python 3.6+
except ImportError:
import collections as collectionsAbc

from past.builtins import xrange

try:
Expand Down Expand Up @@ -38,7 +43,7 @@ def check_contract(self, context, value, silent):

return

if not isinstance(value, collections.Sequence):
if not isinstance(value, collectionsAbc.Sequence):
error = 'Expected a Sequence, got %r.' % value.__class__.__name__
raise ContractNotRespected(self, error, value, context)

Expand Down
7 changes: 5 additions & 2 deletions src/contracts/library/sets.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from ..interface import Contract, ContractNotRespected, describe_type
from ..syntax import (Keyword, O, S, W, add_contract, add_keyword,
contract_expression)
import collections
try:
import collections.abc as collectionsAbc # python 3.6+
except ImportError:
import collections as collectionsAbc


class ASet(Contract):
Expand All @@ -13,7 +16,7 @@ def __init__(self, length_contract=None,
self.elements_contract = elements_contract

def check_contract(self, context, value, silent):
if not isinstance(value, collections.Set):
if not isinstance(value, collectionsAbc.Set):
error = 'Expected a set, got %r.' % describe_type(value)
raise ContractNotRespected(self, error, value, context)

Expand Down
8 changes: 4 additions & 4 deletions src/contracts/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ def tmp_wrap(f): # do not change name (see above)
try:
return contracts_decorate(f, **kwargs)
except ContractSyntaxError as e:
msg = u"Cannot decorate function %s:" % f.__name__
msg = "Cannot decorate function %s:".format(f.__name__)
from .utils import indent
import traceback
msg += u'\n\n' + indent(traceback.format_exc(), u' ')
msg += '\n\n' + indent(traceback.format_exc(), ' ')
raise ContractSyntaxError(msg, e.where)
# erase the stack
except ContractDefinitionError as e:
Expand Down Expand Up @@ -596,7 +596,7 @@ def new_contract_impl(identifier, condition):
loc = e.loc
if loc >= len(identifier):
loc -= 1
where = Where(identifier, character=loc) #line=e.lineno, column=e.col)
where = Where(identifier, character=loc) # line=e.lineno, column=e.col)
# msg = 'Error in parsing string: %s' % e
msg = ('The given identifier %r does not correspond to my idea '
'of what an identifier should look like;\n%s\n%s'
Expand Down Expand Up @@ -659,7 +659,7 @@ def new_contract_impl(identifier, condition):
assert c == expected, \
'Expected %r, got %r.' % (c, expected) # pragma: no cover
except ContractSyntaxError: # pragma: no cover
#assert False, 'Cannot parse %r: %s' % (identifier, e)
# assert False, 'Cannot parse %r: %s' % (identifier, e)
raise

return contract
Expand Down
4 changes: 2 additions & 2 deletions src/contracts/testing/test_unicode_literals.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@

import unittest


class TestParsingNumbers(unittest.TestCase):

def test_unicode_literal(self):
r = parse_contract_string(u'int')
r = parse_contract_string('int')
print(r)

def test_unicode_literal2(self):
Expand All @@ -19,5 +20,4 @@ def test_unicode_literal2(self):
def f(x):
pass


f('')
Loading