Skip to content

Commit

Permalink
Emit a better error message for unevaluatedProperties with a subschema.
Browse files Browse the repository at this point in the history
Closes: #996
  • Loading branch information
Julian committed Nov 17, 2022
1 parent 75903d8 commit 7830605
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 9 deletions.
25 changes: 17 additions & 8 deletions jsonschema/_validators.py
Expand Up @@ -435,23 +435,32 @@ def unevaluatedItems(validator, unevaluatedItems, instance, schema):
def unevaluatedProperties(validator, unevaluatedProperties, instance, schema):
if not validator.is_type(instance, "object"):
return
evaluated_property_keys = find_evaluated_property_keys_by_schema(
evaluated_keys = find_evaluated_property_keys_by_schema(
validator, instance, schema,
)
unevaluated_property_keys = []
unevaluated_keys = []
for property in instance:
if property not in evaluated_property_keys:
if property not in evaluated_keys:
for _ in validator.descend(
instance[property],
unevaluatedProperties,
path=property,
schema_path=property,
):
unevaluated_property_keys.append(property)

if unevaluated_property_keys:
error = "Unevaluated properties are not allowed (%s %s unexpected)"
yield ValidationError(error % extras_msg(unevaluated_property_keys))
# FIXME: Include context for each unevaluated property
# indicating why it's invalid under the subschema.
unevaluated_keys.append(property)

if unevaluated_keys:
if unevaluatedProperties is False:
error = "Unevaluated properties are not allowed (%s %s unexpected)"
yield ValidationError(error % extras_msg(unevaluated_keys))
else:
error = (
"Unevaluated properties are not valid under "
"the given schema (%s %s unevaluated and invalid)"
)
yield ValidationError(error % extras_msg(unevaluated_keys))


def prefixItems(validator, prefixItems, instance, schema):
Expand Down
21 changes: 20 additions & 1 deletion jsonschema/tests/test_validators.py
Expand Up @@ -634,7 +634,26 @@ def test_unevaluated_items_on_invalid_type(self):
message = self.message_for(instance="foo", schema=schema)
self.assertEqual(message, "'foo' is not of type 'array'")

def test_unevaluated_properties(self):
def test_unevaluated_properties_invalid_against_subschema(self):
schema = {
"properties": {"foo": {"type": "string"}},
"unevaluatedProperties": {"const": 12},
}
message = self.message_for(
instance={
"foo": "foo",
"bar": "bar",
"baz": 12,
},
schema=schema,
)
self.assertEqual(
message,
"Unevaluated properties are not valid under the given schema "
"('bar' was unevaluated and invalid)",
)

def test_unevaluated_properties_disallowed(self):
schema = {"type": "object", "unevaluatedProperties": False}
message = self.message_for(
instance={
Expand Down

0 comments on commit 7830605

Please sign in to comment.