forked from eth-cscs/stackinator
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathschema.py
More file actions
123 lines (94 loc) · 4.37 KB
/
schema.py
File metadata and controls
123 lines (94 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import json
import pathlib
from textwrap import dedent
import jsonschema
import yaml
from . import root_logger
prefix = pathlib.Path(__file__).parent.resolve()
def py2yaml(data, indent):
dump = yaml.dump(data)
lines = [ln for ln in dump.split("\n") if ln != ""]
res = ("\n" + " " * indent).join(lines)
return res
def validator(schema):
"""
Create a new validator class that will insert optional fields with their default values
if they have not been provided.
"""
def extend_with_default(validator_class):
validate_properties = validator_class.VALIDATORS["properties"]
def set_defaults(validator, properties, instance, schema):
# if instance is none, it's not possible to set any default for any sub-property
if instance is not None:
for property, subschema in properties.items():
if "default" in subschema:
instance.setdefault(property, subschema["default"])
for error in validate_properties(
validator,
properties,
instance,
schema,
):
yield error
return jsonschema.validators.extend(
validator_class,
{"properties": set_defaults},
)
# try to read dialect metaschema from the $schema entry, otherwise fallback to a default one.
metaschema = jsonschema.validators.validator_for(schema)
return extend_with_default(metaschema)(schema)
class ValidationError(jsonschema.ValidationError):
def __init__(self, name: str, errors: list[jsonschema.ValidationError]):
assert len(errors) != 0
messages = [
f"- Failed validating '{error.validator}' in {error.json_path} : {error.message}" for error in errors
]
message = f"ValidationError in '{name}'\n"
message += "\n".join(messages)
super().__init__(message)
class SchemaValidator:
def __init__(self, schema_filepath: pathlib.Path, precheck=None):
self._validator = validator(json.load(open(schema_filepath)))
self._precheck = precheck
def validate(self, instance: dict):
if self._precheck:
self._precheck(instance)
errors = [error for error in self._validator.iter_errors(instance)]
if len(errors) != 0:
raise ValidationError(self._validator.schema.get("title", "no-title"), errors)
def check_config_version(instance):
rversion = instance.get("version", 1)
if rversion != 2:
if rversion == 1:
root_logger.error(
dedent("""
The recipe is an old version 1 recipe for Spack v0.23 and earlier.
This version of Stackinator supports Spack 1.0, and has deprecated support for Spack v0.23.
Use version 5 of stackinator, which can be accessed via the releases/v5 branch:
git switch releases/v5
If this recipe is to be used with Spack 1.0, then please add the field 'version: 2' to
config.yaml in your recipe.
For more information: https://eth-cscs.github.io/stackinator/recipes/#configuration
""")
)
raise RuntimeError("incompatible uenv recipe version")
else:
root_logger.error(
dedent(f"""
The config.yaml file sets an unknown recipe version={rversion}.
This version of Stackinator supports version 2 recipes.
For more information: https://eth-cscs.github.io/stackinator/recipes/#configuration
""")
)
raise RuntimeError("incompatible uenv recipe version")
def check_module_paths(instance):
try:
instance["modules"]["default"]["roots"]["tcl"]
root_logger.warning("'modules:default:roots:tcl' field is ignored and overwritten by stackinator.")
except KeyError:
pass
ConfigValidator = SchemaValidator(prefix / "schema/config.json", check_config_version)
CompilersValidator = SchemaValidator(prefix / "schema/compilers.json")
EnvironmentsValidator = SchemaValidator(prefix / "schema/environments.json")
CacheValidator = SchemaValidator(prefix / "schema/cache.json")
ModulesValidator = SchemaValidator(prefix / "schema/modules.json", check_module_paths)