schema: additionalKeysAreSpecs (#49221)
Currently we validate all keys as specs, but it's meant to validate only additional keys in all cases.
This commit is contained in:
parent
12fe7aef65
commit
7363047b82
@ -7,8 +7,7 @@
|
|||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
import jsonschema
|
import jsonschema
|
||||||
|
import jsonschema.validators
|
||||||
import llnl.util.lang
|
|
||||||
|
|
||||||
from spack.error import SpecSyntaxError
|
from spack.error import SpecSyntaxError
|
||||||
|
|
||||||
@ -18,59 +17,59 @@ class DeprecationMessage(typing.NamedTuple):
|
|||||||
error: bool
|
error: bool
|
||||||
|
|
||||||
|
|
||||||
# jsonschema is imported lazily as it is heavy to import
|
def _validate_spec(validator, is_spec, instance, schema):
|
||||||
# and increases the start-up time
|
"""Check if all additional keys are valid specs."""
|
||||||
def _make_validator():
|
import spack.spec_parser
|
||||||
def _validate_spec(validator, is_spec, instance, schema):
|
|
||||||
"""Check if the attributes on instance are valid specs."""
|
|
||||||
import spack.spec_parser
|
|
||||||
|
|
||||||
if not validator.is_type(instance, "object"):
|
if not validator.is_type(instance, "object"):
|
||||||
return
|
return
|
||||||
|
|
||||||
for spec_str in instance:
|
properties = schema.get("properties") or {}
|
||||||
try:
|
|
||||||
spack.spec_parser.parse(spec_str)
|
|
||||||
except SpecSyntaxError:
|
|
||||||
yield jsonschema.ValidationError(f"the key '{spec_str}' is not a valid spec")
|
|
||||||
|
|
||||||
def _deprecated_properties(validator, deprecated, instance, schema):
|
for spec_str in instance:
|
||||||
if not (validator.is_type(instance, "object") or validator.is_type(instance, "array")):
|
if spec_str in properties:
|
||||||
return
|
continue
|
||||||
|
try:
|
||||||
if not deprecated:
|
spack.spec_parser.parse(spec_str)
|
||||||
return
|
except SpecSyntaxError:
|
||||||
|
yield jsonschema.ValidationError(f"the key '{spec_str}' is not a valid spec")
|
||||||
deprecations = {
|
|
||||||
name: DeprecationMessage(message=x["message"], error=x["error"])
|
|
||||||
for x in deprecated
|
|
||||||
for name in x["names"]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get a list of the deprecated properties, return if there is none
|
|
||||||
issues = [entry for entry in instance if entry in deprecations]
|
|
||||||
if not issues:
|
|
||||||
return
|
|
||||||
|
|
||||||
# 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(
|
|
||||||
jsonschema.Draft7Validator,
|
|
||||||
{"validate_spec": _validate_spec, "deprecatedProperties": _deprecated_properties},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
Validator = llnl.util.lang.Singleton(_make_validator)
|
def _deprecated_properties(validator, deprecated, instance, schema):
|
||||||
|
if not (validator.is_type(instance, "object") or validator.is_type(instance, "array")):
|
||||||
|
return
|
||||||
|
|
||||||
|
if not deprecated:
|
||||||
|
return
|
||||||
|
|
||||||
|
deprecations = {
|
||||||
|
name: DeprecationMessage(message=x["message"], error=x["error"])
|
||||||
|
for x in deprecated
|
||||||
|
for name in x["names"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get a list of the deprecated properties, return if there is none
|
||||||
|
issues = [entry for entry in instance if entry in deprecations]
|
||||||
|
if not issues:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 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))
|
||||||
|
|
||||||
|
|
||||||
|
Validator = jsonschema.validators.extend(
|
||||||
|
jsonschema.Draft7Validator,
|
||||||
|
{"additionalKeysAreSpecs": _validate_spec, "deprecatedProperties": _deprecated_properties},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _append(string: str) -> bool:
|
def _append(string: str) -> bool:
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
"load": array_of_strings,
|
"load": array_of_strings,
|
||||||
"suffixes": {
|
"suffixes": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"validate_spec": True,
|
"additionalKeysAreSpecs": True,
|
||||||
"additionalProperties": {"type": "string"}, # key
|
"additionalProperties": {"type": "string"}, # key
|
||||||
},
|
},
|
||||||
"environment": spack.schema.environment.definition,
|
"environment": spack.schema.environment.definition,
|
||||||
@ -64,7 +64,7 @@
|
|||||||
tcl_configuration = {
|
tcl_configuration = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"default": {},
|
"default": {},
|
||||||
"validate_spec": True,
|
"additionalKeysAreSpecs": True,
|
||||||
"properties": {**common_props},
|
"properties": {**common_props},
|
||||||
"additionalProperties": module_file_configuration,
|
"additionalProperties": module_file_configuration,
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@
|
|||||||
lmod_configuration = {
|
lmod_configuration = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"default": {},
|
"default": {},
|
||||||
"validate_spec": True,
|
"additionalKeysAreSpecs": True,
|
||||||
"properties": {
|
"properties": {
|
||||||
**common_props,
|
**common_props,
|
||||||
"core_compilers": array_of_strings,
|
"core_compilers": array_of_strings,
|
||||||
@ -80,7 +80,7 @@
|
|||||||
"core_specs": array_of_strings,
|
"core_specs": array_of_strings,
|
||||||
"filter_hierarchy_specs": {
|
"filter_hierarchy_specs": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"validate_spec": True,
|
"additionalKeysAreSpecs": True,
|
||||||
"additionalProperties": array_of_strings,
|
"additionalProperties": array_of_strings,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
def validate_spec_schema():
|
def validate_spec_schema():
|
||||||
return {
|
return {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"validate_spec": True,
|
"additionalKeysAreSpecs": True,
|
||||||
"patternProperties": {r"\w[\w-]*": {"type": "string"}},
|
"patternProperties": {r"\w[\w-]*": {"type": "string"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ def module_suffixes_schema():
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"suffixes": {
|
"suffixes": {
|
||||||
"validate_spec": True,
|
"additionalKeysAreSpecs": True,
|
||||||
"patternProperties": {r"\w[\w-]*": {"type": "string"}},
|
"patternProperties": {r"\w[\w-]*": {"type": "string"}},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user