Skip to content

Commit

Permalink
squash: more verbose messages from schema validation
Browse files Browse the repository at this point in the history
  • Loading branch information
happz committed Apr 17, 2023
1 parent 40d764e commit 68ada59
Showing 1 changed file with 65 additions and 4 deletions.
69 changes: 65 additions & 4 deletions tmt/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import fmf
import fmf.base
import fmf.utils
import jsonschema
from click import confirm, echo, style
from fmf.utils import listed
from ruamel.yaml.error import MarkedYAMLError
Expand Down Expand Up @@ -704,12 +705,72 @@ def _lint_keys(self, additional_keys: List[str]) -> List[str]:
def lint_validate(self) -> LinterReturn:
""" C000: fmf node should pass the schema validation """

errors = tmt.utils.validate_fmf_node(self.node, f'{self.__class__.__name__.lower()}.yaml')
schema_name = self.__class__.__name__.lower()

errors = tmt.utils.validate_fmf_node(self.node, f'{schema_name}.yaml')

if errors:
for exc, message in errors:
# TODO: one day, this should become FAIL
yield LinterOutcome.WARN, f'fmf node failed schema validation, {message}'
# A bit of error formatting. It is possible to use str(error), but the result
# is a bit too JSON-ish. Let's present an error message in a way that helps
# users to point finger on each and every issue.

def detect_unallowed_properties(error: jsonschema.ValidationError) -> LinterReturn:
match = re.search(
r"(?mi)Additional properties are not allowed \(([a-zA-Z0-9', \-]+) (?:was|were) unexpected\)", # noqa: E501
str(error))

if not match:
return

for bad_property in match.group(1).replace("'", '').replace(' ', '').split(','):
yield LinterOutcome.WARN, \
f'key "{bad_property}" not recognized by schema {error.schema["$id"]}'

# A key value is not recognized. This is often a case with keys whose values are
# limited by an enum, like `how`. Unfortunatelly, validator will record every mismatch
# between a value and enum even if eventually a match is found. So it might be tempting
# to ignore this particular kind of error - it may also indicate a genuine typo in
# key name or completely misplaced key, so it's still necessary to report the error.
def detect_enum_violations(error: jsonschema.ValidationError) -> LinterReturn:
match = re.search(
r"(?mi)'([a-z\-]+)' is not one of \['([a-zA-Z\-]+)'\]",
str(error))

if not match:
return

yield LinterOutcome.WARN, \
f'value of "{error.json_path.split(".")[-1]}" is not "{match.group(2)}"'

for error, _ in errors:
# if error.path:
# # Path to a place in tested instance where the error appeared
# error_path = '.'.join(error.path)
#
# yield LinterOutcome.WARN, textwrap.dedent(f"""
# At key "{error_path}":
#
# -----
# {error_path}:
# {textwrap.indent(tmt.utils.dict_to_yaml(error.instance), ' ')}
# -----
# """)
#
# else:
# yield LinterOutcome.WARN, textwrap.dedent(f"""
# -----
# {textwrap.indent(tmt.utils.dict_to_yaml(error.instance), ' ')}
# -----
# """)

yield from detect_unallowed_properties(error)
yield from detect_enum_violations(error)

# Validation errors can have "context", a list of "sub" errors encountered during
# validation. Interesting ones are identified & added to our error message.
for suberror in error.context:
yield from detect_unallowed_properties(suberror)
yield from detect_enum_violations(suberror)

return

Expand Down

0 comments on commit 68ada59

Please sign in to comment.