I am using voluptuous
a lot to validate yaml description files. Often the errors are cumbersome to decipher, especially for regular users.
I am looking for a way to make the error a bit more readable. One way is to identify which line in the YAML file is incrimined.
from voluptuous import Schema
import yaml
from io import StringIO
Validate = Schema({
'name': str,
'age': int,
})
data = """
name: John
age: oops
"""
data = Validate(yaml.load(StringIO(data)))
In the above example, I get this error:
MultipleInvalid: expected int for dictionary value @ data['age']
I would rather prefer an error like:
Error: validation failed on line 2, data.age should be an integer.
Is there an elegant way to achieve this?
With the help of flyx I found ruamel.yaml
which provide the line and col of a parsed YAML file. So one can manage to get the wanted error with:
from voluptuous import Schema
from ruamel.yaml import load, RoundTripLoader
from io import StringIO
Validate = Schema({
'name': {
'firstname': str,
'lastname': str
},
'age': int,
})
data = """
name:
firstname: John
lastname: 12.0
age: 42
"""
class Validate:
def __init__(self, stream):
self._yaml = load(stream, Loader=RoundTripLoader)
return self.validate()
def validate(self):
try:
self.data = Criteria(self._yaml)
except Invalid as e:
node = self._yaml
for key in e.path:
if (hasattr(node[key], '_yaml_line_col')):
node = node[key]
else:
break
path = '/'.join(e.path)
print(f"Error: validation failed on line {node._yaml_line_col.line}:{node._yaml_line_col.col} (/{path}): {e.error_message}")
else:
return self.data
data = Validate(StringIO(data))
With this I get this error message:
Error: validation failed on line 2:4 (/name): extra keys not allowed