Skip to content

Commit

Permalink
Merge pull request #12 from OpenDataServices/cove-bods-16-oneof-only
Browse files Browse the repository at this point in the history
Improve validation error messages for oneOf
  • Loading branch information
Bjwebb authored Mar 25, 2019
2 parents 5e1d05c + 9fc8323 commit 4dbfd5f
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 6 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Return specific validation errors for `oneOf`, by using `statementType` to pick the correct sub-schema. Only works for BODS. [#16](https://github.com/openownership/cove-bods/issues/16)

## [0.4.0] - 2019-03-14

### Changed
Expand Down
46 changes: 40 additions & 6 deletions libcove/lib/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,22 +86,56 @@ def oneOf_draft4(validator, oneOf, instance, schema):
"""
oneOf_draft4 validator from
https://github.com/Julian/jsonschema/blob/d16713a4296663f3d62c50b9f9a2893cb380b7af/jsonschema/_validators.py#L337
patched to sort the instance.
Modified to:
- sort the instance JSON, so we get a reproducible output that we
can can test more easily
- If `statementType` is available, use that pick the correct
sub-schema, and to yield those ValidationErrors. (Only
applicable for BODS).
"""
subschemas = enumerate(oneOf)
all_errors = []
validStatementTypes = []
for index, subschema in subschemas:
errs = list(validator.descend(instance, subschema, schema_path=index))
if not errs:
first_valid = subschema
break
properties = subschema.get('properties', {})
if'statementType' in properties:
if 'statementType' in instance:
try:
validStatementType = properties['statementType'].get('enum', [])[0]
except IndexError:
continue
if instance['statementType'] == validStatementType:
for err in errs:
yield err
return
else:
validStatementTypes.append(validStatementType)
else:
yield ValidationError(
'statementType',
validator='required',
)
break
all_errors.extend(errs)
else:
yield ValidationError(
"%s is not valid under any of the given schemas" % (
json.dumps(instance, sort_keys=True, default=decimal_default),),
context=all_errors,
)
if validStatementTypes:
yield ValidationError(
'Invalid code found in statementType',
instance=instance['statementType'],
path=('statementType',),
validator='enum',
)
else:
yield ValidationError(
"%s is not valid under any of the given schemas" % (
json.dumps(instance, sort_keys=True, default=decimal_default),),
context=all_errors,
)

more_valid = [s for i, s in subschemas if validator.is_valid(instance, s)]
if more_valid:
Expand Down

0 comments on commit 4dbfd5f

Please sign in to comment.