Allow deprecating more than one property in config (#46221)
* Allow deprecating more than one property in config This internal change allows the customization of errors and warnings to be printed when deprecating a property. Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com> * fix Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com> * Use a list comprehension for "issues" Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com> --------- Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
This commit is contained in:
parent
434a703bcf
commit
9a8bff01ad
@ -3,22 +3,28 @@
|
|||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
"""This module contains jsonschema files for all of Spack's YAML formats."""
|
"""This module contains jsonschema files for all of Spack's YAML formats."""
|
||||||
|
import typing
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
import llnl.util.lang
|
import llnl.util.lang
|
||||||
|
|
||||||
|
|
||||||
|
class DeprecationMessage(typing.NamedTuple):
|
||||||
|
message: str
|
||||||
|
error: bool
|
||||||
|
|
||||||
|
|
||||||
# jsonschema is imported lazily as it is heavy to import
|
# jsonschema is imported lazily as it is heavy to import
|
||||||
# and increases the start-up time
|
# and increases the start-up time
|
||||||
def _make_validator():
|
def _make_validator():
|
||||||
import jsonschema
|
import jsonschema
|
||||||
|
|
||||||
import spack.parser
|
|
||||||
|
|
||||||
def _validate_spec(validator, is_spec, instance, schema):
|
def _validate_spec(validator, is_spec, instance, schema):
|
||||||
"""Check if the attributes on instance are valid specs."""
|
"""Check if the attributes on instance are valid specs."""
|
||||||
import jsonschema
|
import jsonschema
|
||||||
|
|
||||||
|
import spack.parser
|
||||||
|
|
||||||
if not validator.is_type(instance, "object"):
|
if not validator.is_type(instance, "object"):
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -32,27 +38,31 @@ def _deprecated_properties(validator, deprecated, instance, schema):
|
|||||||
if not (validator.is_type(instance, "object") or validator.is_type(instance, "array")):
|
if not (validator.is_type(instance, "object") or validator.is_type(instance, "array")):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Get a list of the deprecated properties, return if there is none
|
if not deprecated:
|
||||||
deprecated_properties = [x for x in instance if x in deprecated["properties"]]
|
|
||||||
if not deprecated_properties:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Retrieve the template message
|
deprecations = {
|
||||||
msg_str_or_func = deprecated["message"]
|
name: DeprecationMessage(message=x["message"], error=x["error"])
|
||||||
if isinstance(msg_str_or_func, str):
|
for x in deprecated
|
||||||
msg = msg_str_or_func.format(properties=deprecated_properties)
|
for name in x["names"]
|
||||||
else:
|
}
|
||||||
msg = msg_str_or_func(instance, deprecated_properties)
|
|
||||||
if msg is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
is_error = deprecated["error"]
|
# Get a list of the deprecated properties, return if there is none
|
||||||
if not is_error:
|
issues = [entry for entry in instance if entry in deprecations]
|
||||||
warnings.warn(msg)
|
if not issues:
|
||||||
else:
|
return
|
||||||
import jsonschema
|
|
||||||
|
|
||||||
yield jsonschema.ValidationError(msg)
|
# Process issues
|
||||||
|
errors = []
|
||||||
|
for name in issues:
|
||||||
|
msg = deprecations[name].message.format(name=name)
|
||||||
|
if deprecations[name].error:
|
||||||
|
errors.append(msg)
|
||||||
|
else:
|
||||||
|
warnings.warn(msg)
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
yield jsonschema.ValidationError("\n".join(errors))
|
||||||
|
|
||||||
return jsonschema.validators.extend(
|
return jsonschema.validators.extend(
|
||||||
jsonschema.Draft4Validator,
|
jsonschema.Draft4Validator,
|
||||||
|
@ -96,12 +96,14 @@
|
|||||||
"binary_index_ttl": {"type": "integer", "minimum": 0},
|
"binary_index_ttl": {"type": "integer", "minimum": 0},
|
||||||
"aliases": {"type": "object", "patternProperties": {r"\w[\w-]*": {"type": "string"}}},
|
"aliases": {"type": "object", "patternProperties": {r"\w[\w-]*": {"type": "string"}}},
|
||||||
},
|
},
|
||||||
"deprecatedProperties": {
|
"deprecatedProperties": [
|
||||||
"properties": ["concretizer"],
|
{
|
||||||
"message": "Spack supports only clingo as a concretizer from v0.23. "
|
"names": ["concretizer"],
|
||||||
"The config:concretizer config option is ignored.",
|
"message": "Spack supports only clingo as a concretizer from v0.23. "
|
||||||
"error": False,
|
"The config:concretizer config option is ignored.",
|
||||||
},
|
"error": False,
|
||||||
|
}
|
||||||
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,14 +140,16 @@
|
|||||||
},
|
},
|
||||||
"variants": variants,
|
"variants": variants,
|
||||||
},
|
},
|
||||||
"deprecatedProperties": {
|
"deprecatedProperties": [
|
||||||
"properties": ["version"],
|
{
|
||||||
"message": "setting version preferences in the 'all' section of packages.yaml "
|
"names": ["version"],
|
||||||
"is deprecated and will be removed in v0.23\n\n\tThese preferences "
|
"message": "setting version preferences in the 'all' section of "
|
||||||
"will be ignored by Spack. You can set them only in package-specific sections "
|
"packages.yaml is deprecated and will be removed in v0.23"
|
||||||
"of the same file.\n",
|
"\n\n\tThese preferences will be ignored by Spack. You can "
|
||||||
"error": False,
|
"set them only in package-specific sections of the same file.\n",
|
||||||
},
|
"error": False,
|
||||||
|
}
|
||||||
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"patternProperties": {
|
"patternProperties": {
|
||||||
@ -204,18 +206,20 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"deprecatedProperties": {
|
"deprecatedProperties": [
|
||||||
"properties": ["target", "compiler", "providers"],
|
{
|
||||||
"message": "setting 'compiler:', 'target:' or 'provider:' preferences in "
|
"names": ["target", "compiler", "providers"],
|
||||||
"a package-specific section of packages.yaml is deprecated, and will be "
|
"message": "setting '{name}:' preferences in "
|
||||||
"removed in v0.23.\n\n\tThese preferences will be ignored by Spack, and "
|
"a package-specific section of packages.yaml is deprecated, and will be "
|
||||||
"can be set only in the 'all' section of the same file. "
|
"removed in v0.23.\n\n\tThis preferences will be ignored by Spack, and "
|
||||||
"You can run:\n\n\t\t$ spack audit configs\n\n\tto get better diagnostics, "
|
"can be set only in the 'all' section of the same file. "
|
||||||
"including files:lines where the deprecated attributes are used.\n\n"
|
"You can run:\n\n\t\t$ spack audit configs\n\n\tto get better "
|
||||||
"\tUse requirements to enforce conditions on specific packages: "
|
"diagnostics, including files:lines where the deprecated "
|
||||||
f"{REQUIREMENT_URL}\n",
|
"attributes are used.\n\n\tUse requirements to enforce conditions"
|
||||||
"error": False,
|
f" on specific packages: {REQUIREMENT_URL}\n",
|
||||||
},
|
"error": False,
|
||||||
|
}
|
||||||
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -105,25 +105,21 @@ def test_schema_validation(meta_schema, config_name):
|
|||||||
|
|
||||||
def test_deprecated_properties(module_suffixes_schema):
|
def test_deprecated_properties(module_suffixes_schema):
|
||||||
# Test that an error is reported when 'error: True'
|
# Test that an error is reported when 'error: True'
|
||||||
msg_fmt = r"deprecated properties detected [properties={properties}]"
|
msg_fmt = r"{name} is deprecated"
|
||||||
module_suffixes_schema["deprecatedProperties"] = {
|
module_suffixes_schema["deprecatedProperties"] = [
|
||||||
"properties": ["tcl"],
|
{"names": ["tcl"], "message": msg_fmt, "error": True}
|
||||||
"message": msg_fmt,
|
]
|
||||||
"error": True,
|
|
||||||
}
|
|
||||||
v = spack.schema.Validator(module_suffixes_schema)
|
v = spack.schema.Validator(module_suffixes_schema)
|
||||||
data = {"tcl": {"all": {"suffixes": {"^python": "py"}}}}
|
data = {"tcl": {"all": {"suffixes": {"^python": "py"}}}}
|
||||||
|
|
||||||
expected_match = "deprecated properties detected"
|
expected_match = "tcl is deprecated"
|
||||||
with pytest.raises(jsonschema.ValidationError, match=expected_match):
|
with pytest.raises(jsonschema.ValidationError, match=expected_match):
|
||||||
v.validate(data)
|
v.validate(data)
|
||||||
|
|
||||||
# Test that just a warning is reported when 'error: False'
|
# Test that just a warning is reported when 'error: False'
|
||||||
module_suffixes_schema["deprecatedProperties"] = {
|
module_suffixes_schema["deprecatedProperties"] = [
|
||||||
"properties": ["tcl"],
|
{"names": ["tcl"], "message": msg_fmt, "error": False}
|
||||||
"message": msg_fmt,
|
]
|
||||||
"error": False,
|
|
||||||
}
|
|
||||||
v = spack.schema.Validator(module_suffixes_schema)
|
v = spack.schema.Validator(module_suffixes_schema)
|
||||||
data = {"tcl": {"all": {"suffixes": {"^python": "py"}}}}
|
data = {"tcl": {"all": {"suffixes": {"^python": "py"}}}}
|
||||||
# The next validation doesn't raise anymore
|
# The next validation doesn't raise anymore
|
||||||
|
Loading…
Reference in New Issue
Block a user