Skip to content

Commit

Permalink
Improve 'oneOf' error messages
Browse files Browse the repository at this point in the history
'oneOf' failures are hard because the messages give little indication of
which of the oneOf clauses is most likely what needs to be fixed.

The jsonschema.best_match() method can help in some cases when the errors
have different schema depths.

The handling for more than 1 oneOf condition being true is worse than the
default for jsonschema as it prints the whole oneOf schema rather than just
the true cases. I think jsonschema improved this at some point. With that,
we can just remove the custom formatting.

Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
  • Loading branch information
robherring committed May 3, 2024
1 parent 0f006b1 commit 1a2c5d8
Showing 1 changed file with 15 additions and 16 deletions.
31 changes: 15 additions & 16 deletions dtschema/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
# Python library for Devicetree schema validation
import os
import re
import pprint

from jsonschema.exceptions import best_match

# We use a lot of regex's in schema and exceeding the cache size has noticeable
# peformance impact.
Expand Down Expand Up @@ -128,21 +129,19 @@ def format_error(filename, error, prefix="", nodename=None, verbose=False):
elif not error.schema_path:
msg = error.message
elif error.context:
# An error on a conditional will have context with sub-errors
msg = "'" + error.schema_path[-1] + "' conditional failed, one must be fixed:"

for suberror in sorted(error.context, key=lambda e: e.path):
if suberror.context:
msg += '\n' + format_error(filename, suberror, prefix=prefix+"\t", nodename=nodename, verbose=verbose)
elif suberror.message not in msg:
msg += '\n' + prefix + '\t' + suberror.message
if hasattr(suberror, 'note') and suberror.note and suberror.note != error.note:
msg += '\n\t\t' + prefix + 'hint: ' + suberror.note

elif error.schema_path[-1] == 'oneOf':
msg = 'More than one condition true in oneOf schema:\n\t' + \
'\t'.join(pprint.pformat(error.schema, width=72).splitlines(True))

if len(error.context) == 1:
msg = best_match(error.context).message
else:
# An error on a conditional will have context with sub-errors
msg = "\n'" + error.schema_path[-1] + "' conditional failed, one must be fixed:"

for suberror in sorted(error.context, key=lambda e: e.path):
if suberror.context:
msg += '\n' + format_error(filename, suberror, prefix=prefix+"\t", nodename=nodename, verbose=verbose)
elif suberror.message not in msg:
msg += '\n' + prefix + '\t' + suberror.message
if hasattr(suberror, 'note') and suberror.note and suberror.note != error.note:
msg += '\n\t\t' + prefix + 'hint: ' + suberror.note
else:
msg = error.message

Expand Down

0 comments on commit 1a2c5d8

Please sign in to comment.