Skip to content

Commit

Permalink
global: enum validation function fix
Browse files Browse the repository at this point in the history
* FIX Fixes enum error in validation function.

Signed-off-by: PaulinaLach <paulina.malgorzata.lach@cern.ch>
  • Loading branch information
Paulina1 committed Aug 30, 2016
1 parent e1ae7b7 commit 9dd3184
Show file tree
Hide file tree
Showing 2 changed files with 226 additions and 31 deletions.
75 changes: 44 additions & 31 deletions doschema/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ class JSONSchemaValidator(object):

COLLECTION_KEYS = frozenset(['allOf', 'anyOf', 'oneOf'])

python_to_json_types_map = {
"list": "array",
"bool": "boolean",
"int": "integer",
"float": "number",
"complex": "number",
"NoneType": "null",
"dict": "object",
"str": "string"
}

def __init__(self, ignore_index=True, resolver_factory=False):
"""Constructor.
Expand Down Expand Up @@ -95,6 +106,7 @@ def _validate_root(self, curr_schema, curr_field):

field = self.fields_types_dict.get(curr_field)

field_type = curr_schema.get('type')
if "type" in curr_schema:
if field is not None and field.field_type == 'null':
raise NotImplementedError(
Expand All @@ -112,8 +124,6 @@ def _validate_root(self, curr_schema, curr_field):
field.schema_index
)

field_type = curr_schema['type']

if field_type == 'null':
raise NotImplementedError(
'JSON schema null type is not supported.'
Expand All @@ -127,40 +137,34 @@ def _validate_root(self, curr_schema, curr_field):
)

if curr_schema['type'] == 'array':
self._validate_array(
curr_schema['items'],
curr_field + ('items',)
)
if curr_schema.get('items') is not None:
self._validate_array(
curr_schema['items'],
curr_field + ('items',)
)
if "enum" in curr_schema:
enum_type = self._validate_enum(
guessed_enum_type = self._validate_enum(
curr_schema['enum'],
curr_field
)
if field is not None and field.field_type != enum_type:
err_msg = """Conflicting type for field {0} previously found
in schema {1} enum with type {2},
found next with type {3}."""
if field_type and field_type != guessed_enum_type:
err_msg = "Predicted enum type {0} conflicting with " \
"properties type {1} in schema {2}"
raise JSONSchemaCompatibilityError(
err_msg.format(
self.make_json_pointer(curr_field),
self.uri,
field.schema_index,
field.field_type
guessed_enum_type,
field_type,
self.uri
),
self.uri,
field.schema_index
self.uri
)
self.fields_types_dict[curr_field] = field = FieldToAdd(
schema_index=self.uri,
field_tuple=curr_field,
field_type=enum_type
)

if 'properties' in curr_schema:
if field and field.field_type != "object":
err_msg = """Conflicting type for field {0} previously found
in schema {1} with type {2}, found next in {3}
where "dependencies" imply type "object"."""
err_msg = "Conflicting type for field {0} previously found " \
"in schema {1} with type {2}, found next in {3} " \
"where 'properties' imply type 'object'."
raise JSONSchemaCompatibilityError(
err_msg.format(
self.make_json_pointer(curr_field),
Expand All @@ -177,16 +181,17 @@ def _validate_root(self, curr_schema, curr_field):
field_type='object'
)
for prop in curr_schema['properties']:
self._validate_root(
curr_schema['properties'][prop],
curr_field + (prop,)
)
if isinstance(curr_schema['properties'][prop], dict):
self._validate_root(
curr_schema['properties'][prop],
curr_field + (prop,)
)

if "dependencies" in curr_schema:
if field and field.field_type != "object":
err_msg = """Conflicting type for field {0} previously found
in schema {1} with type {2}, found next in {3}
where "dependencies" imply type "object"."""
err_msg = "Conflicting type for field {0} previously found " \
"in schema {1} with type {2}, found next in {3} " \
"where 'dependencies' imply type 'object'."
raise JSONSchemaCompatibilityError(
err_msg.format(
self.make_json_pointer(curr_field),
Expand Down Expand Up @@ -295,6 +300,14 @@ def _validate_enum(self, field_value, path):
),
self.uri
)
if isinstance(field_value[0], dict) \
or isinstance(field_value[0], list):
raise NotImplementedError(
'JSON schema {0} type inside enum is not supported.'.format(
field_value[0].__class__.__name__
)
)
return self.python_to_json_types_map[field_value[0].__class__.__name__]

@staticmethod
def make_json_pointer(path):
Expand Down
182 changes: 182 additions & 0 deletions tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,34 @@ def test_root_not_object():
obj.validate(v1, 'first')


def test_type_conflict_with_properties_implied():
"""Test that having type given in schema and type 'object' implied by
properties fails."""
v1 = {
"type": "string",
"properties": {
"field_a": {"type": "string"}
}
}
obj = JSONSchemaValidator()
with pytest.raises(JSONSchemaCompatibilityError):
obj.validate(v1, 'first')


def test_type_conflict_with_dependencies_implied():
"""Test that having type given in schema and type 'object' implied by
dependencies fails."""
v1 = {
"type": "string",
"dependencies": {
"field_a": {"type": "string"}
}
}
obj = JSONSchemaValidator()
with pytest.raises(JSONSchemaCompatibilityError):
obj.validate(v1, 'first')


def test_dependencies_not_dict():
"""Test the exception raised when dependencies are neither of type list
nor a dict."""
Expand Down Expand Up @@ -208,6 +236,136 @@ def test_conflict_in_dependencies():
obj.validate(v1, 'first')


def test_array_no_items_pass():
"""Test that having an array without items passes."""
v1 = {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"$schema": {"type": "string"},
"_files": {
"type": "array"
}
}
}
obj = JSONSchemaValidator()
obj.validate(v1, 'first')


def test_different_types_inside_enum():
"""Test that having different types inside enum fails."""
v1 = {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"resource_type": {
"type": "array",
"items": {
"enum": [
"Text",
42
]
}
}
}
}
obj = JSONSchemaValidator()
with pytest.raises(JSONSchemaCompatibilityError):
obj.validate(v1, 'first')


def test_enum_in_array_items_pass():
"""Test that having enum in array's items passes."""
v1 = {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"$schema": {"type": "string"},
"resource_type": {
"title": "Resource Type",
"description": "The type of the resource.",
"type": "array",
"items": {
"type": "string",
"enum": [
"Text",
"Image",
"Video",
"Audio",
"Time-Series",
"Other"
]
},
"uniqueItems": True
}
},
"required": ["community", "title", "open_access"]
}
obj = JSONSchemaValidator()
obj.validate(v1, 'first')


def test_different_types_given_and_guessed_enum():
"""Tets that having type given in schema and different type guessed from
enum fails."""
v1 = {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"resource_type": {
"type": "integer",
"enum": [
"Text",
"Image"
]
}
}
}
obj = JSONSchemaValidator()
with pytest.raises(JSONSchemaCompatibilityError):
obj.validate(v1, 'first')


def test_dict_type_inside_enum():
"Test that having a dict inside enum fails."
v1 = {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"resource_type": {
"type": "array",
"items": {
"enum": [{
"field_A": {"type": "string"}
}]
}
}
}
}
obj = JSONSchemaValidator()
with pytest.raises(NotImplementedError):
obj.validate(v1, 'first')


def test_list_type_inside_enum():
"Test that having a list inside enum fails."
v1 = {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"resource_type": {
"type": "array",
"items": {
"enum": [['abc'], ['bdc']]
}
}
}
}
obj = JSONSchemaValidator()
with pytest.raises(NotImplementedError):
obj.validate(v1, 'first')


def test_no_conflict_in_collection_pass():
"""Test that having no conflict between elements of a collection passes."""
v1 = {
Expand Down Expand Up @@ -450,6 +608,30 @@ def test_null_type_not_implemented():
obj.validate(v1, 'first')


def test_null_type_repeated_fields():
"""Test that having already used field using it with type null fails."""
v1 = {
"type": "object",
"properties": {
"abc": {
"type": "string"
}
}
}
v2 = {
"type": "object",
"properties": {
"abc": {
"type": "null"
}
}
}
obj = JSONSchemaValidator()
obj.validate(v1, 'first')
with pytest.raises(JSONSchemaCompatibilityError):
obj.validate(v2, 'second')


def test_not_ignoring_indices_pass():
"""Test that with option 'ignore index' set to False and different types
in array passes."""
Expand Down

0 comments on commit 9dd3184

Please sign in to comment.