Skip to content

Commit

Permalink
Added support for schema constraints (#55)
Browse files Browse the repository at this point in the history
* updated jsontableschema version

* implemented all constraints except unique

* implemented unique constraint check

* updated to jsontableschema-v0.8.2

* fixed linting
  • Loading branch information
roll committed Oct 29, 2016
1 parent 08f8255 commit 66c5aea
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 20 deletions.
13 changes: 11 additions & 2 deletions goodtables/checks/body/constraints/enumerable_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@

@check('enumerable-constraint')
def enumerable_constraint(errors, columns, row_number, state=None):
# https://github.com/frictionlessdata/goodtables-py/issues/116
for column in columns:
if len(column) == 4:
pass
valid = column['field'].test_value(column['value'], constraint='enum')
if not valid:
# Add error
message = 'Row %s has enum constraint violation in column %s'
message = message % (row_number, column['number'])
errors.append({
'code': 'enumerable-constraint',
'message': message,
'row-number': row_number,
'column-number': column['number'],
})
13 changes: 11 additions & 2 deletions goodtables/checks/body/constraints/maximum_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@

@check('maximum-constraint')
def maximum_constraint(errors, columns, row_number, state=None):
# https://github.com/frictionlessdata/goodtables-py/issues/116
for column in columns:
if len(column) == 4:
pass
valid = column['field'].test_value(column['value'], constraint='maximum')
if not valid:
# Add error
message = 'Row %s has maximum constraint violation in column %s'
message = message % (row_number, column['number'])
errors.append({
'code': 'maximum-constraint',
'message': message,
'row-number': row_number,
'column-number': column['number'],
})
13 changes: 11 additions & 2 deletions goodtables/checks/body/constraints/maximum_length_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@

@check('maximum-length-constraint')
def maximum_length_constraint(errors, columns, row_number, state=None):
# https://github.com/frictionlessdata/goodtables-py/issues/116
for column in columns:
if len(column) == 4:
pass
valid = column['field'].test_value(column['value'], constraint='maxLength')
if not valid:
# Add error
message = 'Row %s has maxLength constraint violation in column %s'
message = message % (row_number, column['number'])
errors.append({
'code': 'maximum-length-constraint',
'message': message,
'row-number': row_number,
'column-number': column['number'],
})
13 changes: 11 additions & 2 deletions goodtables/checks/body/constraints/minimum_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@

@check('minimum-constraint')
def minimum_constraint(errors, columns, row_number, state=None):
# https://github.com/frictionlessdata/goodtables-py/issues/116
for column in columns:
if len(column) == 4:
pass
valid = column['field'].test_value(column['value'], constraint='minimum')
if not valid:
# Add error
message = 'Row %s has minimum constraint violation in column %s'
message = message % (row_number, column['number'])
errors.append({
'code': 'minimum-constraint',
'message': message,
'row-number': row_number,
'column-number': column['number'],
})
13 changes: 11 additions & 2 deletions goodtables/checks/body/constraints/minimum_length_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@

@check('minimum-length-constraint')
def minimum_length_constraint(errors, columns, row_number, state=None):
# https://github.com/frictionlessdata/goodtables-py/issues/116
for column in columns:
if len(column) == 4:
pass
valid = column['field'].test_value(column['value'], constraint='minLength')
if not valid:
# Add error
message = 'Row %s has minLength constraint violation in column %s'
message = message % (row_number, column['number'])
errors.append({
'code': 'minimum-length-constraint',
'message': message,
'row-number': row_number,
'column-number': column['number'],
})
18 changes: 15 additions & 3 deletions goodtables/checks/body/constraints/pattern_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,26 @@
from __future__ import absolute_import
from __future__ import unicode_literals

from copy import copy
from ....register import check


# Module API

@check('pattern-constraint')
def pattern_constraint(errors, columns, row_number, state=None):
# https://github.com/frictionlessdata/goodtables-py/issues/116
for column in columns:
for column in copy(columns):
if len(column) == 4:
pass
valid = column['field'].test_value(column['value'], constraint='pattern')
if not valid:
# Add error
message = 'Row %s has pattern constraint violation in column %s'
message = message % (row_number, column['number'])
errors.append({
'code': 'pattern-constraint',
'message': message,
'row-number': row_number,
'column-number': column['number'],
})
# Remove column
columns.remove(column)
18 changes: 15 additions & 3 deletions goodtables/checks/body/constraints/required_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,26 @@
from __future__ import absolute_import
from __future__ import unicode_literals

from copy import copy
from ....register import check


# Module API

@check('required-constraint')
def required_constraint(errors, columns, row_number, state=None):
# https://github.com/frictionlessdata/goodtables-py/issues/116
for column in columns:
for column in copy(columns):
if len(column) == 4:
pass
valid = column['field'].test_value(column['value'], constraint='required')
if not valid:
# Add error
message = 'Row %s has required constraint violation in column %s'
message = message % (row_number, column['number'])
errors.append({
'code': 'required-constraint',
'message': message,
'row-number': row_number,
'column-number': column['number'],
})
# Remove column
columns.remove(column)
18 changes: 16 additions & 2 deletions goodtables/checks/body/constraints/unique_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,21 @@

@check('unique-constraint')
def unique_constraint(errors, columns, row_number, state):
# https://github.com/frictionlessdata/goodtables-py/issues/116
rindexes = state.setdefault('cache', {})
for column in columns:
if len(column) == 4:
pass
if column['field'].constraints.get('unique'):
rindex = rindexes.setdefault(column['number'], {})
references = rindex.setdefault(column['value'], [])
if references:
# Add error
mesrows = ', '.join(map(str, references + [row_number]))
message = 'Rows %s has unique constraint violation in column %s'
message = message % (mesrows, column['number'])
errors.append({
'code': 'unique-constraint',
'message': message,
'row-number': row_number,
'column-number': column['number'],
})
references.append(row_number)
3 changes: 2 additions & 1 deletion goodtables/checks/body/non_castable_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ def non_castable_value(errors, columns, row_number, state=None):
for column in copy(columns):
if len(column) == 4:
try:
column['value'] = column['field'].cast_value(column['value'])
column['value'] = column['field'].cast_value(
column['value'], skip_constraints=True)
except jsontableschema.exceptions.JsonTableSchemaException:
# Add error
message = 'Row %s has non castable value in column %s'
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def read(*paths):
'click>=6.6,<7.0a',
'requests>=2.10,<3.0a',
'tabulator>=0.10,<1.0a',
'jsontableschema>=0.7,<1.0a',
'jsontableschema>=0.8.2,<1.0a',
'datapackage>=0.8,<1.0a',
]
TESTS_REQUIRE = [
Expand Down

0 comments on commit 66c5aea

Please sign in to comment.