Improve warning message for deprecated attributes in "packages.yaml"

The deprecatedProperties custom validator now can accept a function
to compute a better error message.

Improve error/warning message for deprecated properties
This commit is contained in:
Massimiliano Culpo 2020-08-12 11:57:32 +02:00 committed by Todd Gamblin
parent c9ad2affcc
commit 89181f253b
6 changed files with 67 additions and 28 deletions

View File

@ -598,9 +598,6 @@ def _get_config_memoized(self, section, scope):
changed = _update_in_memory(data, section)
if changed:
self.format_updates[section].append(scope)
msg = ('OUTDATED CONFIGURATION FILE '
'[section={0}, scope={1}, dir={2}]')
tty.debug(msg.format(section, scope.name, scope.path))
merged_section = merge_yaml(merged_section, data)

View File

@ -2,7 +2,6 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""This module contains jsonschema files for all of Spack's YAML formats."""
import copy
@ -86,19 +85,18 @@ def _deprecated_properties(validator, deprecated, instance, schema):
return
# Retrieve the template message
msg = deprecated['message']
msg_str_or_func = deprecated['message']
if isinstance(msg_str_or_func, six.string_types):
msg = msg_str_or_func.format(properties=deprecated_properties)
else:
msg = msg_str_or_func(instance, deprecated_properties)
is_error = deprecated['error']
if not is_error:
for entry in deprecated_properties:
llnl.util.tty.warn(
msg.format(property=entry, entry=instance[entry])
)
llnl.util.tty.warn(msg)
else:
import jsonschema
for entry in deprecated_properties:
yield jsonschema.ValidationError(
msg.format(property=entry, entry=instance[entry])
)
yield jsonschema.ValidationError(msg)
return jsonschema.validators.extend(
jsonschema.Draft4Validator, {

View File

@ -63,9 +63,9 @@
},
'deprecatedProperties': {
'properties': ['dotkit'],
'message': 'specifying a "{property}" module root has no '
'effect [support for {property} module files'
' has been dropped]',
'message': 'specifying a "dotkit" module root has no '
'effect [support for "dotkit" has been '
'dropped in v0.13.0]',
'error': False
},
},

View File

@ -135,9 +135,9 @@
},
'deprecatedProperties': {
'properties': ['dotkit'],
'message': 'cannot enable "{property}" in modules.yaml '
'[support for {property} module files has been'
' dropped]',
'message': 'cannot enable "dotkit" in modules.yaml '
'[support for "dotkit" has been dropped '
'in v0.13.0]',
'error': False
},
},
@ -172,9 +172,8 @@
},
'deprecatedProperties': {
'properties': ['dotkit'],
'message': 'the section "{property}" in modules.yaml has no effect'
' [support for {property} module files has been '
'dropped]',
'message': 'the "dotkit" section in modules.yaml has no effect'
' [support for "dotkit" has been dropped in v0.13.0]',
'error': False
},
},

View File

@ -9,6 +9,51 @@
"""
def deprecate_paths_and_modules(instance, deprecated_properties):
"""Function to produce warning/error messages if "paths" and "modules" are
found in "packages.yaml"
Args:
instance: instance of the configuration file
deprecated_properties: deprecated properties in instance
Returns:
Warning/Error message to be printed
"""
import copy
import os.path
import llnl.util.tty
import spack.util.spack_yaml as syaml
# Copy the instance to remove default attributes that are not related
# to the part that needs to be reported
instance_copy = copy.copy(instance)
# Check if this configuration comes from an environment or not
absolute_path = instance_copy._end_mark.name
command_to_suggest = '$ spack config update packages'
if os.path.basename(absolute_path) == 'spack.yaml':
command_to_suggest = '$ spack env update <environment>'
# Retrieve the relevant part of the configuration as YAML
keys_to_be_removed = [
x for x in instance_copy if x not in deprecated_properties
]
for key in keys_to_be_removed:
instance_copy.pop(key)
yaml_as_str = syaml.dump_config(instance_copy, blame=True)
if llnl.util.tty.is_debug():
msg = 'OUTDATED CONFIGURATION FILE [file={0}]\n{1}'
llnl.util.tty.debug(msg.format(absolute_path, yaml_as_str))
msg = ('detected deprecated properties in {0}\nActivate the debug '
'flag to have more information on the deprecated parts or '
'run:\n\n\t{2}\n\nto update the file to the new format\n')
return msg.format(
absolute_path, yaml_as_str, command_to_suggest
)
#: Properties for inclusion in other schemas
properties = {
'packages': {
@ -95,9 +140,7 @@
},
'deprecatedProperties': {
'properties': ['modules', 'paths'],
'message': 'the attribute "{property}" in the "packages" '
'section of the configuration has been '
'deprecated [entry={entry}]',
'message': deprecate_paths_and_modules,
'error': False
}
},

View File

@ -118,21 +118,23 @@ def test_schema_validation(meta_schema, config_name):
def test_deprecated_properties(module_suffixes_schema):
# Test that an error is reported when 'error: True'
msg_fmt = r'deprecated properties detected [properties={properties}]'
module_suffixes_schema['deprecatedProperties'] = {
'properties': ['tcl'],
'message': '{property} not allowed',
'message': msg_fmt,
'error': True
}
v = spack.schema.Validator(module_suffixes_schema)
data = {'tcl': {'all': {'suffixes': {'^python': 'py'}}}}
with pytest.raises(jsonschema.ValidationError, match='tcl not allowed'):
expected_match = 'deprecated properties detected'
with pytest.raises(jsonschema.ValidationError, match=expected_match):
v.validate(data)
# Test that just a warning is reported when 'error: False'
module_suffixes_schema['deprecatedProperties'] = {
'properties': ['tcl'],
'message': '{property} not allowed',
'message': msg_fmt,
'error': False
}
v = spack.schema.Validator(module_suffixes_schema)