parent
dcead12e86
commit
bec73245e9
4 changed files with 29 additions and 26 deletions
3
NEWS
3
NEWS
|
@ -1,3 +1,6 @@
|
||||||
|
1.5.23.dev0
|
||||||
|
* #480, #482: Fix traceback when a YAML validation error occurs.
|
||||||
|
|
||||||
1.5.22
|
1.5.22
|
||||||
* #288: Add database dump hook for MongoDB.
|
* #288: Add database dump hook for MongoDB.
|
||||||
* #470: Move mysqldump options to the beginning of the command due to MySQL bug 30994.
|
* #470: Move mysqldump options to the beginning of the command due to MySQL bug 30994.
|
||||||
|
|
|
@ -15,7 +15,7 @@ def schema_filename():
|
||||||
return pkg_resources.resource_filename('borgmatic', 'config/schema.yaml')
|
return pkg_resources.resource_filename('borgmatic', 'config/schema.yaml')
|
||||||
|
|
||||||
|
|
||||||
def format_error_path_element(path_element):
|
def format_json_error_path_element(path_element):
|
||||||
'''
|
'''
|
||||||
Given a path element into a JSON data structure, format it for display as a string.
|
Given a path element into a JSON data structure, format it for display as a string.
|
||||||
'''
|
'''
|
||||||
|
@ -25,14 +25,14 @@ def format_error_path_element(path_element):
|
||||||
return str('.{}'.format(path_element))
|
return str('.{}'.format(path_element))
|
||||||
|
|
||||||
|
|
||||||
def format_error(error):
|
def format_json_error(error):
|
||||||
'''
|
'''
|
||||||
Given an instance of jsonschema.exceptions.ValidationError, format it for display as a string.
|
Given an instance of jsonschema.exceptions.ValidationError, format it for display as a string.
|
||||||
'''
|
'''
|
||||||
if not error.path:
|
if not error.path:
|
||||||
return 'At the top level: {}'.format(error.message)
|
return 'At the top level: {}'.format(error.message)
|
||||||
|
|
||||||
formatted_path = ''.join(format_error_path_element(element) for element in error.path)
|
formatted_path = ''.join(format_json_error_path_element(element) for element in error.path)
|
||||||
return "At '{}': {}".format(formatted_path.lstrip('.'), error.message)
|
return "At '{}': {}".format(formatted_path.lstrip('.'), error.message)
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ class Validation_error(ValueError):
|
||||||
|
|
||||||
def __init__(self, config_filename, errors):
|
def __init__(self, config_filename, errors):
|
||||||
'''
|
'''
|
||||||
Given a configuration filename path and a sequence of
|
Given a configuration filename path and a sequence of string error messages, create a
|
||||||
jsonschema.exceptions.ValidationError instances, create a Validation_error.
|
Validation_error.
|
||||||
'''
|
'''
|
||||||
self.config_filename = config_filename
|
self.config_filename = config_filename
|
||||||
self.errors = errors
|
self.errors = errors
|
||||||
|
@ -56,7 +56,7 @@ class Validation_error(ValueError):
|
||||||
'''
|
'''
|
||||||
return 'An error occurred while parsing a configuration file at {}:\n'.format(
|
return 'An error occurred while parsing a configuration file at {}:\n'.format(
|
||||||
self.config_filename
|
self.config_filename
|
||||||
) + '\n'.join(format_error(error) for error in self.errors)
|
) + '\n'.join(error for error in self.errors)
|
||||||
|
|
||||||
|
|
||||||
def apply_logical_validation(config_filename, parsed_configuration):
|
def apply_logical_validation(config_filename, parsed_configuration):
|
||||||
|
@ -117,7 +117,9 @@ def parse_configuration(config_filename, schema_filename, overrides=None):
|
||||||
validation_errors = tuple(validator.iter_errors(config))
|
validation_errors = tuple(validator.iter_errors(config))
|
||||||
|
|
||||||
if validation_errors:
|
if validation_errors:
|
||||||
raise Validation_error(config_filename, validation_errors)
|
raise Validation_error(
|
||||||
|
config_filename, tuple(format_json_error(error) for error in validation_errors)
|
||||||
|
)
|
||||||
|
|
||||||
apply_logical_validation(config_filename, config)
|
apply_logical_validation(config_filename, config)
|
||||||
|
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -1,6 +1,6 @@
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
VERSION = '1.5.22'
|
VERSION = '1.5.23.dev0'
|
||||||
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
|
|
|
@ -4,33 +4,31 @@ from flexmock import flexmock
|
||||||
from borgmatic.config import validate as module
|
from borgmatic.config import validate as module
|
||||||
|
|
||||||
|
|
||||||
def test_format_error_path_element_formats_array_index():
|
def test_format_json_error_path_element_formats_array_index():
|
||||||
module.format_error_path_element(3) == '[3]'
|
module.format_json_error_path_element(3) == '[3]'
|
||||||
|
|
||||||
|
|
||||||
def test_format_error_path_element_formats_property():
|
def test_format_json_error_path_element_formats_property():
|
||||||
module.format_error_path_element('foo') == '.foo'
|
module.format_json_error_path_element('foo') == '.foo'
|
||||||
|
|
||||||
|
|
||||||
def test_format_error_formats_error_including_path():
|
def test_format_json_error_formats_error_including_path():
|
||||||
flexmock(module).format_error_path_element = lambda element: '.{}'.format(element)
|
flexmock(module).format_json_error_path_element = lambda element: '.{}'.format(element)
|
||||||
error = flexmock(message='oops', path=['foo', 'bar'])
|
error = flexmock(message='oops', path=['foo', 'bar'])
|
||||||
|
|
||||||
assert module.format_error(error) == "At 'foo.bar': oops"
|
assert module.format_json_error(error) == "At 'foo.bar': oops"
|
||||||
|
|
||||||
|
|
||||||
def test_format_error_formats_error_without_path():
|
def test_format_json_error_formats_error_without_path():
|
||||||
flexmock(module).should_receive('format_error_path_element').never()
|
flexmock(module).should_receive('format_json_error_path_element').never()
|
||||||
error = flexmock(message='oops', path=[])
|
error = flexmock(message='oops', path=[])
|
||||||
|
|
||||||
assert module.format_error(error) == 'At the top level: oops'
|
assert module.format_json_error(error) == 'At the top level: oops'
|
||||||
|
|
||||||
|
|
||||||
def test_validation_error_string_contains_error_messages_and_config_filename():
|
def test_validation_error_string_contains_errors():
|
||||||
flexmock(module).format_error = lambda error: error.message
|
flexmock(module).format_json_error = lambda error: error.message
|
||||||
error = module.Validation_error(
|
error = module.Validation_error('config.yaml', ('oops', 'uh oh'))
|
||||||
'config.yaml', (flexmock(message='oops', path=None), flexmock(message='uh oh'))
|
|
||||||
)
|
|
||||||
|
|
||||||
result = str(error)
|
result = str(error)
|
||||||
|
|
||||||
|
@ -40,7 +38,7 @@ def test_validation_error_string_contains_error_messages_and_config_filename():
|
||||||
|
|
||||||
|
|
||||||
def test_apply_logical_validation_raises_if_archive_name_format_present_without_prefix():
|
def test_apply_logical_validation_raises_if_archive_name_format_present_without_prefix():
|
||||||
flexmock(module).format_error = lambda error: error.message
|
flexmock(module).format_json_error = lambda error: error.message
|
||||||
|
|
||||||
with pytest.raises(module.Validation_error):
|
with pytest.raises(module.Validation_error):
|
||||||
module.apply_logical_validation(
|
module.apply_logical_validation(
|
||||||
|
@ -53,7 +51,7 @@ def test_apply_logical_validation_raises_if_archive_name_format_present_without_
|
||||||
|
|
||||||
|
|
||||||
def test_apply_logical_validation_raises_if_archive_name_format_present_without_retention_prefix():
|
def test_apply_logical_validation_raises_if_archive_name_format_present_without_retention_prefix():
|
||||||
flexmock(module).format_error = lambda error: error.message
|
flexmock(module).format_json_error = lambda error: error.message
|
||||||
|
|
||||||
with pytest.raises(module.Validation_error):
|
with pytest.raises(module.Validation_error):
|
||||||
module.apply_logical_validation(
|
module.apply_logical_validation(
|
||||||
|
@ -67,7 +65,7 @@ def test_apply_logical_validation_raises_if_archive_name_format_present_without_
|
||||||
|
|
||||||
|
|
||||||
def test_apply_locical_validation_raises_if_unknown_repository_in_check_repositories():
|
def test_apply_locical_validation_raises_if_unknown_repository_in_check_repositories():
|
||||||
flexmock(module).format_error = lambda error: error.message
|
flexmock(module).format_json_error = lambda error: error.message
|
||||||
|
|
||||||
with pytest.raises(module.Validation_error):
|
with pytest.raises(module.Validation_error):
|
||||||
module.apply_logical_validation(
|
module.apply_logical_validation(
|
||||||
|
|
Loading…
Reference in a new issue