summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2018-08-20 17:04:52 -0700
committerTodd Gamblin <tgamblin@llnl.gov>2018-11-09 00:31:24 -0800
commitc19000038bd7b56c08013b7063a2d891c845358a (patch)
tree917f50d14d5e3df57546846da29165a3afa38dd7
parent83323f4e71afdbeadfdc445c901d319c9b0e01d2 (diff)
downloadspack-c19000038bd7b56c08013b7063a2d891c845358a.tar.gz
spack-c19000038bd7b56c08013b7063a2d891c845358a.tar.bz2
spack-c19000038bd7b56c08013b7063a2d891c845358a.tar.xz
spack-c19000038bd7b56c08013b7063a2d891c845358a.zip
schemas: rework schemas so that they can be included from other files
- Each schema now has a top-level `properties` and `schema` attribute. - The `properties` is a fragment that can be included in other jsonschemas, via Python, not via '$ref' - Th `schema` is a complete `jsonschema` with `title` and `$schema` properties.
-rw-r--r--lib/spack/spack/config.py23
-rw-r--r--lib/spack/spack/environment.py1
-rw-r--r--lib/spack/spack/schema/__init__.py10
-rw-r--r--lib/spack/spack/schema/compilers.py201
-rw-r--r--lib/spack/spack/schema/config.py99
-rw-r--r--lib/spack/spack/schema/env.py15
-rw-r--r--lib/spack/spack/schema/mirrors.py26
-rw-r--r--lib/spack/spack/schema/modules.py296
-rw-r--r--lib/spack/spack/schema/packages.py141
-rw-r--r--lib/spack/spack/schema/repos.py20
-rw-r--r--lib/spack/spack/test/config.py64
11 files changed, 496 insertions, 400 deletions
diff --git a/lib/spack/spack/config.py b/lib/spack/spack/config.py
index 179972299e..0d2d5046a9 100644
--- a/lib/spack/spack/config.py
+++ b/lib/spack/spack/config.py
@@ -51,7 +51,12 @@ from llnl.util.filesystem import mkdirp
import spack.paths
import spack.architecture
-import spack.schema
+import spack.schema.compilers
+import spack.schema.mirrors
+import spack.schema.repos
+import spack.schema.packages
+import spack.schema.modules
+import spack.schema.config
from spack.error import SpackError
# Hacked yaml for configuration files preserves line numbers.
@@ -175,7 +180,7 @@ class ConfigScope(object):
try:
mkdirp(self.path)
with open(filename, 'w') as f:
- _validate_section(data, section_schemas[section])
+ _validate(data, section_schemas[section])
syaml.dump(data, stream=f, default_flow_style=False)
except (yaml.YAMLError, IOError) as e:
raise ConfigFileError(
@@ -216,7 +221,7 @@ class InternalConfigScope(ConfigScope):
if data:
for section in data:
dsec = data[section]
- _validate_section({section: dsec}, section_schemas[section])
+ _validate({section: dsec}, section_schemas[section])
self.sections[section] = _mark_internal(
syaml.syaml_dict({section: dsec}), name)
@@ -234,7 +239,7 @@ class InternalConfigScope(ConfigScope):
"""This only validates, as the data is already in memory."""
data = self.get_section(section)
if data is not None:
- _validate_section(data, section_schemas[section])
+ _validate(data, section_schemas[section])
self.sections[section] = _mark_internal(data, self.name)
def __repr__(self):
@@ -585,7 +590,7 @@ def _validate_section_name(section):
% (section, " ".join(section_schemas.keys())))
-def _validate_section(data, schema):
+def _validate(data, schema):
"""Validate data read in from a Spack YAML file.
This leverages the line information (start_mark, end_mark) stored
@@ -593,13 +598,13 @@ def _validate_section(data, schema):
"""
import jsonschema
- if not hasattr(_validate_section, 'validator'):
+ if not hasattr(_validate, 'validator'):
default_setting_validator = _extend_with_default(
jsonschema.Draft4Validator)
- _validate_section.validator = default_setting_validator
+ _validate.validator = default_setting_validator
try:
- _validate_section.validator(schema).validate(data)
+ _validate.validator(schema).validate(data)
except jsonschema.ValidationError as e:
raise ConfigFormatError(e, data)
@@ -623,7 +628,7 @@ def _read_config_file(filename, schema):
data = _mark_overrides(syaml.load(f))
if data:
- _validate_section(data, schema)
+ _validate(data, schema)
return data
except MarkedYAMLError as e:
diff --git a/lib/spack/spack/environment.py b/lib/spack/spack/environment.py
index cc34f8a7ba..5b745c6c9b 100644
--- a/lib/spack/spack/environment.py
+++ b/lib/spack/spack/environment.py
@@ -85,7 +85,6 @@ def deactivate():
return
-
def root(name):
"""Get the root directory for an environment by name."""
return fs.join_path(env_path, name)
diff --git a/lib/spack/spack/schema/__init__.py b/lib/spack/spack/schema/__init__.py
index f2533f2cc2..b7a90827f2 100644
--- a/lib/spack/spack/schema/__init__.py
+++ b/lib/spack/spack/schema/__init__.py
@@ -3,12 +3,4 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-"""This module contains jsonschema files for all of Spack's YAML formats.
-"""
-from llnl.util.lang import list_modules
-
-# Automatically bring in all sub-modules
-__all__ = []
-for mod in list_modules(__path__[0]):
- __import__('%s.%s' % (__name__, mod))
- __all__.append(mod)
+"""This module contains jsonschema files for all of Spack's YAML formats."""
diff --git a/lib/spack/spack/schema/compilers.py b/lib/spack/spack/schema/compilers.py
index ab09767221..139462d2d4 100644
--- a/lib/spack/spack/schema/compilers.py
+++ b/lib/spack/spack/schema/compilers.py
@@ -10,114 +10,119 @@
"""
-schema = {
- '$schema': 'http://json-schema.org/schema#',
- 'title': 'Spack compiler configuration file schema',
- 'type': 'object',
- 'additionalProperties': False,
- 'properties': {
- 'compilers': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'additionalProperties': False,
- 'properties': {
- 'compiler': {
- 'type': 'object',
- 'additionalProperties': False,
- 'required': [
- 'paths', 'spec', 'modules', 'operating_system'],
- 'properties': {
- 'paths': {
- 'type': 'object',
- 'required': ['cc', 'cxx', 'f77', 'fc'],
- 'additionalProperties': False,
- 'properties': {
- 'cc': {'anyOf': [{'type': 'string'},
+#: Properties for inclusion in other schemas
+properties = {
+ 'compilers': {
+ 'type': 'array',
+ 'items': [{
+ 'type': 'object',
+ 'additionalProperties': False,
+ 'properties': {
+ 'compiler': {
+ 'type': 'object',
+ 'additionalProperties': False,
+ 'required': [
+ 'paths', 'spec', 'modules', 'operating_system'],
+ 'properties': {
+ 'paths': {
+ 'type': 'object',
+ 'required': ['cc', 'cxx', 'f77', 'fc'],
+ 'additionalProperties': False,
+ 'properties': {
+ 'cc': {'anyOf': [{'type': 'string'},
+ {'type': 'null'}]},
+ 'cxx': {'anyOf': [{'type': 'string'},
+ {'type': 'null'}]},
+ 'f77': {'anyOf': [{'type': 'string'},
+ {'type': 'null'}]},
+ 'fc': {'anyOf': [{'type': 'string'},
+ {'type': 'null'}]}}},
+ 'flags': {
+ 'type': 'object',
+ 'additionalProperties': False,
+ 'properties': {
+ 'cflags': {'anyOf': [{'type': 'string'},
+ {'type': 'null'}]},
+ 'cxxflags': {'anyOf': [{'type': 'string'},
+ {'type': 'null'}]},
+ 'fflags': {'anyOf': [{'type': 'string'},
+ {'type': 'null'}]},
+ 'cppflags': {'anyOf': [{'type': 'string'},
+ {'type': 'null'}]},
+ 'ldflags': {'anyOf': [{'type': 'string'},
{'type': 'null'}]},
- 'cxx': {'anyOf': [{'type': 'string'},
- {'type': 'null'}]},
- 'f77': {'anyOf': [{'type': 'string'},
- {'type': 'null'}]},
- 'fc': {'anyOf': [{'type': 'string'},
- {'type': 'null'}]}}},
- 'flags': {
- 'type': 'object',
- 'additionalProperties': False,
- 'properties': {
- 'cflags': {'anyOf': [{'type': 'string'},
- {'type': 'null'}]},
- 'cxxflags': {'anyOf': [{'type': 'string'},
- {'type': 'null'}]},
- 'fflags': {'anyOf': [{'type': 'string'},
- {'type': 'null'}]},
- 'cppflags': {'anyOf': [{'type': 'string'},
- {'type': 'null'}]},
- 'ldflags': {'anyOf': [{'type': 'string'},
- {'type': 'null'}]},
- 'ldlibs': {'anyOf': [{'type': 'string'},
- {'type': 'null'}]}}},
- 'spec': {'type': 'string'},
- 'operating_system': {'type': 'string'},
- 'target': {'type': 'string'},
- 'alias': {'anyOf': [{'type': 'string'},
- {'type': 'null'}]},
- 'modules': {'anyOf': [{'type': 'string'},
- {'type': 'null'},
- {'type': 'array'}]},
- 'environment': {
- 'type': 'object',
- 'default': {},
- 'additionalProperties': False,
- 'properties': {
- 'set': {
- 'type': 'object',
- 'patternProperties': {
- # Variable name
- r'\w[\w-]*': {
- 'anyOf': [{'type': 'string'},
- {'type': 'number'}]
- }
- }
- },
- 'unset': {
- 'type': 'object',
- 'patternProperties': {
- # Variable name
- r'\w[\w-]*': {'type': 'null'}
+ 'ldlibs': {'anyOf': [{'type': 'string'},
+ {'type': 'null'}]}}},
+ 'spec': {'type': 'string'},
+ 'operating_system': {'type': 'string'},
+ 'target': {'type': 'string'},
+ 'alias': {'anyOf': [{'type': 'string'},
+ {'type': 'null'}]},
+ 'modules': {'anyOf': [{'type': 'string'},
+ {'type': 'null'},
+ {'type': 'array'}]},
+ 'environment': {
+ 'type': 'object',
+ 'default': {},
+ 'additionalProperties': False,
+ 'properties': {
+ 'set': {
+ 'type': 'object',
+ 'patternProperties': {
+ # Variable name
+ r'\w[\w-]*': {
+ 'anyOf': [{'type': 'string'},
+ {'type': 'number'}]
}
- },
- 'prepend-path': {
- 'type': 'object',
- 'patternProperties': {
- # Variable name
- r'\w[\w-]*': {
- 'anyOf': [{'type': 'string'},
- {'type': 'number'}]
- }
+ }
+ },
+ 'unset': {
+ 'type': 'object',
+ 'patternProperties': {
+ # Variable name
+ r'\w[\w-]*': {'type': 'null'}
+ }
+ },
+ 'prepend-path': {
+ 'type': 'object',
+ 'patternProperties': {
+ # Variable name
+ r'\w[\w-]*': {
+ 'anyOf': [{'type': 'string'},
+ {'type': 'number'}]
}
- },
- 'append-path': {
- 'type': 'object',
- 'patternProperties': {
- # Variable name
- r'\w[\w-]*': {
- 'anyOf': [{'type': 'string'},
- {'type': 'number'}]
- }
+ }
+ },
+ 'append-path': {
+ 'type': 'object',
+ 'patternProperties': {
+ # Variable name
+ r'\w[\w-]*': {
+ 'anyOf': [{'type': 'string'},
+ {'type': 'number'}]
}
}
}
- },
- 'extra_rpaths': {
- 'type': 'array',
- 'default': [],
- 'items': {'type': 'string'}
}
+ },
+ 'extra_rpaths': {
+ 'type': 'array',
+ 'default': [],
+ 'items': {'type': 'string'}
}
}
}
}
- }
+ }]
}
}
+
+
+#: Full schema with metadata
+schema = {
+ '$schema': 'http://json-schema.org/schema#',
+ 'title': 'Spack compiler configuration file schema',
+ 'type': 'object',
+ 'additionalProperties': False,
+ 'properties': properties,
+}
diff --git a/lib/spack/spack/schema/config.py b/lib/spack/spack/schema/config.py
index 583fe79fbf..0558a7a9ae 100644
--- a/lib/spack/spack/schema/config.py
+++ b/lib/spack/spack/schema/config.py
@@ -10,56 +10,61 @@
"""
+#: Properties for inclusion in other schemas
+properties = {
+ 'config': {
+ 'type': 'object',
+ 'default': {},
+ 'properties': {
+ 'install_tree': {'type': 'string'},
+ 'install_hash_length': {'type': 'integer', 'minimum': 1},
+ 'install_path_scheme': {'type': 'string'},
+ 'build_stage': {
+ 'oneOf': [
+ {'type': 'string'},
+ {'type': 'array',
+ 'items': {'type': 'string'}}],
+ },
+ 'template_dirs': {
+ 'type': 'array',
+ 'items': {'type': 'string'}
+ },
+ 'module_roots': {
+ 'type': 'object',
+ 'additionalProperties': False,
+ 'properties': {
+ 'tcl': {'type': 'string'},
+ 'lmod': {'type': 'string'},
+ 'dotkit': {'type': 'string'},
+ },
+ },
+ 'source_cache': {'type': 'string'},
+ 'misc_cache': {'type': 'string'},
+ 'verify_ssl': {'type': 'boolean'},
+ 'debug': {'type': 'boolean'},
+ 'checksum': {'type': 'boolean'},
+ 'locks': {'type': 'boolean'},
+ 'dirty': {'type': 'boolean'},
+ 'build_language': {'type': 'string'},
+ 'build_jobs': {'type': 'integer', 'minimum': 1},
+ 'ccache': {'type': 'boolean'},
+ 'db_lock_timeout': {'type': 'integer', 'minimum': 1},
+ 'package_lock_timeout': {
+ 'anyOf': [
+ {'type': 'integer', 'minimum': 1},
+ {'type': 'null'}
+ ],
+ },
+ },
+ },
+}
+
+
+#: Full schema with metadata
schema = {
'$schema': 'http://json-schema.org/schema#',
'title': 'Spack core configuration file schema',
'type': 'object',
'additionalProperties': False,
- 'patternProperties': {
- 'config': {
- 'type': 'object',
- 'default': {},
- 'properties': {
- 'install_tree': {'type': 'string'},
- 'install_hash_length': {'type': 'integer', 'minimum': 1},
- 'install_path_scheme': {'type': 'string'},
- 'build_stage': {
- 'oneOf': [
- {'type': 'string'},
- {'type': 'array',
- 'items': {'type': 'string'}}],
- },
- 'template_dirs': {
- 'type': 'array',
- 'items': {'type': 'string'}
- },
- 'module_roots': {
- 'type': 'object',
- 'additionalProperties': False,
- 'properties': {
- 'tcl': {'type': 'string'},
- 'lmod': {'type': 'string'},
- 'dotkit': {'type': 'string'},
- },
- },
- 'source_cache': {'type': 'string'},
- 'misc_cache': {'type': 'string'},
- 'verify_ssl': {'type': 'boolean'},
- 'debug': {'type': 'boolean'},
- 'checksum': {'type': 'boolean'},
- 'locks': {'type': 'boolean'},
- 'dirty': {'type': 'boolean'},
- 'build_language': {'type': 'string'},
- 'build_jobs': {'type': 'integer', 'minimum': 1},
- 'ccache': {'type': 'boolean'},
- 'db_lock_timeout': {'type': 'integer', 'minimum': 1},
- 'package_lock_timeout': {
- 'anyOf': [
- {'type': 'integer', 'minimum': 1},
- {'type': 'null'}
- ],
- },
- }
- },
- },
+ 'properties': properties,
}
diff --git a/lib/spack/spack/schema/env.py b/lib/spack/spack/schema/env.py
index dab4d6a5bd..676d65ec62 100644
--- a/lib/spack/spack/schema/env.py
+++ b/lib/spack/spack/schema/env.py
@@ -12,19 +12,22 @@
schema = {
'$schema': 'http://json-schema.org/schema#',
- 'title': 'Spack Environments user configuration file schema',
+ 'title': 'Spack environment file schema',
'type': 'object',
'additionalProperties': False,
- 'properties': {
- 'env': {
+ 'patternProperties': {
+ '^env|spack$': {
'type': 'object',
'default': {},
'properties': {
- 'configs': {
+ 'include': {
'type': 'array',
- 'default': [],
- 'items': {'type': 'string'}
+ 'items': {
+ 'type': 'string'
+ },
},
+
+
'specs': {
'type': 'object',
'default': {},
diff --git a/lib/spack/spack/schema/mirrors.py b/lib/spack/spack/schema/mirrors.py
index 8832552660..345f43db66 100644
--- a/lib/spack/spack/schema/mirrors.py
+++ b/lib/spack/spack/schema/mirrors.py
@@ -10,20 +10,24 @@
"""
+#: Properties for inclusion in other schemas
+properties = {
+ 'mirrors': {
+ 'type': 'object',
+ 'default': {},
+ 'additionalProperties': False,
+ 'patternProperties': {
+ r'\w[\w-]*': {'type': 'string'},
+ },
+ },
+}
+
+
+#: Full schema with metadata
schema = {
'$schema': 'http://json-schema.org/schema#',
'title': 'Spack mirror configuration file schema',
'type': 'object',
'additionalProperties': False,
- 'patternProperties': {
- r'mirrors': {
- 'type': 'object',
- 'default': {},
- 'additionalProperties': False,
- 'patternProperties': {
- r'\w[\w-]*': {
- 'type': 'string'},
- },
- },
- },
+ 'properties': properties,
}
diff --git a/lib/spack/spack/schema/modules.py b/lib/spack/spack/schema/modules.py
index d1dc9c7605..0a54856105 100644
--- a/lib/spack/spack/schema/modules.py
+++ b/lib/spack/spack/schema/modules.py
@@ -10,158 +10,170 @@
"""
-schema = {
- '$schema': 'http://json-schema.org/schema#',
- 'title': 'Spack module file configuration file schema',
- 'type': 'object',
- 'additionalProperties': False,
- 'definitions': {
- 'array_of_strings': {
- 'type': 'array',
- 'default': [],
- 'items': {
+#: Definitions for parts of module schema
+definitions = {
+ 'array_of_strings': {
+ 'type': 'array',
+ 'default': [],
+ 'items': {
+ 'type': 'string'
+ }
+ },
+ 'dictionary_of_strings': {
+ 'type': 'object',
+ 'patternProperties': {
+ r'\w[\w-]*': { # key
'type': 'string'
}
- },
- 'dictionary_of_strings': {
- 'type': 'object',
- 'patternProperties': {
- r'\w[\w-]*': { # key
- 'type': 'string'
- }
- }
- },
- 'dependency_selection': {
- 'type': 'string',
- 'enum': ['none', 'direct', 'all']
- },
- 'module_file_configuration': {
- 'type': 'object',
- 'default': {},
- 'additionalProperties': False,
- 'properties': {
- 'filter': {
- 'type': 'object',
- 'default': {},
- 'additionalProperties': False,
- 'properties': {
- 'environment_blacklist': {
- 'type': 'array',
- 'default': [],
- 'items': {
- 'type': 'string'
- }
+ }
+ },
+ 'dependency_selection': {
+ 'type': 'string',
+ 'enum': ['none', 'direct', 'all']
+ },
+ 'module_file_configuration': {
+ 'type': 'object',
+ 'default': {},
+ 'additionalProperties': False,
+ 'properties': {
+ 'filter': {
+ 'type': 'object',
+ 'default': {},
+ 'additionalProperties': False,
+ 'properties': {
+ 'environment_blacklist': {
+ 'type': 'array',
+ 'default': [],
+ 'items': {
+ 'type': 'string'
}
}
+ }
+ },
+ 'template': {
+ 'type': 'string'
+ },
+ 'autoload': {
+ '$ref': '#/definitions/dependency_selection'},
+ 'prerequisites': {
+ '$ref': '#/definitions/dependency_selection'},
+ 'conflict': {
+ '$ref': '#/definitions/array_of_strings'},
+ 'load': {
+ '$ref': '#/definitions/array_of_strings'},
+ 'suffixes': {
+ '$ref': '#/definitions/dictionary_of_strings'},
+ 'environment': {
+ 'type': 'object',
+ 'default': {},
+ 'additionalProperties': False,
+ 'properties': {
+ 'set': {
+ '$ref': '#/definitions/dictionary_of_strings'},
+ 'unset': {
+ '$ref': '#/definitions/array_of_strings'},
+ 'prepend_path': {
+ '$ref': '#/definitions/dictionary_of_strings'},
+ 'append_path': {
+ '$ref': '#/definitions/dictionary_of_strings'}
+ }
+ }
+ }
+ },
+ 'module_type_configuration': {
+ 'type': 'object',
+ 'default': {},
+ 'anyOf': [
+ {'properties': {
+ 'verbose': {
+ 'type': 'boolean',
+ 'default': False
},
- 'template': {
- 'type': 'string'
+ 'hash_length': {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'default': 7
},
- 'autoload': {
- '$ref': '#/definitions/dependency_selection'},
- 'prerequisites': {
- '$ref': '#/definitions/dependency_selection'},
- 'conflict': {
+ 'whitelist': {
'$ref': '#/definitions/array_of_strings'},
- 'load': {
+ 'blacklist': {
'$ref': '#/definitions/array_of_strings'},
- 'suffixes': {
- '$ref': '#/definitions/dictionary_of_strings'},
- 'environment': {
- 'type': 'object',
- 'default': {},
- 'additionalProperties': False,
- 'properties': {
- 'set': {
- '$ref': '#/definitions/dictionary_of_strings'},
- 'unset': {
- '$ref': '#/definitions/array_of_strings'},
- 'prepend_path': {
- '$ref': '#/definitions/dictionary_of_strings'},
- 'append_path': {
- '$ref': '#/definitions/dictionary_of_strings'}
- }
+ 'blacklist_implicits': {
+ 'type': 'boolean',
+ 'default': False
+ },
+ 'naming_scheme': {
+ 'type': 'string' # Can we be more specific here?
}
- }
- },
- 'module_type_configuration': {
- 'type': 'object',
- 'default': {},
- 'anyOf': [
- {'properties': {
- 'verbose': {
- 'type': 'boolean',
- 'default': False
- },
- 'hash_length': {
- 'type': 'integer',
- 'minimum': 0,
- 'default': 7
- },
- 'whitelist': {
- '$ref': '#/definitions/array_of_strings'},
- 'blacklist': {
- '$ref': '#/definitions/array_of_strings'},
- 'blacklist_implicits': {
- 'type': 'boolean',
- 'default': False
- },
- 'naming_scheme': {
- 'type': 'string' # Can we be more specific here?
- }
- }},
- {'patternProperties': {
+ }},
+ {'patternProperties': {
+ r'\w[\w-]*': {
+ '$ref': '#/definitions/module_file_configuration'
+ }
+ }}
+ ]
+ }
+}
+
+
+# Properties for inclusion into other schemas (requires definitions)
+properties = {
+ 'modules': {
+ 'type': 'object',
+ 'default': {},
+ 'additionalProperties': False,
+ 'properties': {
+ 'prefix_inspections': {
+ 'type': 'object',
+ 'patternProperties': {
+ # prefix-relative path to be inspected for existence
r'\w[\w-]*': {
- '$ref': '#/definitions/module_file_configuration'
- }
- }}
- ]
- }
- },
- 'patternProperties': {
- r'modules': {
- 'type': 'object',
- 'default': {},
- 'additionalProperties': False,
- 'properties': {
- 'prefix_inspections': {
- 'type': 'object',
- 'patternProperties': {
- # prefix-relative path to be inspected for existence
- r'\w[\w-]*': {
- '$ref': '#/definitions/array_of_strings'}}},
- 'enable': {
- 'type': 'array',
- 'default': [],
- 'items': {
- 'type': 'string',
- 'enum': ['tcl', 'dotkit', 'lmod']}},
- 'lmod': {
- 'allOf': [
- # Base configuration
- {'$ref': '#/definitions/module_type_configuration'},
- {
- 'core_compilers': {
- '$ref': '#/definitions/array_of_strings'
- },
- 'hierarchical_scheme': {
- '$ref': '#/definitions/array_of_strings'
- }
- } # Specific lmod extensions
- ]},
- 'tcl': {
- 'allOf': [
- # Base configuration
- {'$ref': '#/definitions/module_type_configuration'},
- {} # Specific tcl extensions
- ]},
- 'dotkit': {
- 'allOf': [
- # Base configuration
- {'$ref': '#/definitions/module_type_configuration'},
- {} # Specific dotkit extensions
- ]},
- }
+ '$ref': '#/definitions/array_of_strings'}}},
+ 'enable': {
+ 'type': 'array',
+ 'default': [],
+ 'items': {
+ 'type': 'string',
+ 'enum': ['tcl', 'dotkit', 'lmod']}},
+ 'lmod': {
+ 'allOf': [
+ # Base configuration
+ {'$ref': '#/definitions/module_type_configuration'},
+ {
+ 'core_compilers': {
+ '$ref': '#/definitions/array_of_strings'
+ },
+ 'hierarchical_scheme': {
+ '$ref': '#/definitions/array_of_strings'
+ }
+ } # Specific lmod extensions
+ ]
+ },
+ 'tcl': {
+ 'allOf': [
+ # Base configuration
+ {'$ref': '#/definitions/module_type_configuration'},
+ {} # Specific tcl extensions
+ ]
+ },
+ 'dotkit': {
+ 'allOf': [
+ # Base configuration
+ {'$ref': '#/definitions/module_type_configuration'},
+ {} # Specific dotkit extensions
+ ]
+ },
},
},
}
+
+
+#: Full schema with metadata
+schema = {
+ '$schema': 'http://json-schema.org/schema#',
+ 'title': 'Spack module file configuration file schema',
+ 'definitions': definitions,
+ 'type': 'object',
+ 'additionalProperties': False,
+ 'properties': properties,
+}
diff --git a/lib/spack/spack/schema/packages.py b/lib/spack/spack/schema/packages.py
index a8782fc23b..c762a75ba4 100644
--- a/lib/spack/spack/schema/packages.py
+++ b/lib/spack/spack/schema/packages.py
@@ -10,79 +10,84 @@
"""
-schema = {
- '$schema': 'http://json-schema.org/schema#',
- 'title': 'Spack package configuration file schema',
- 'type': 'object',
- 'additionalProperties': False,
- 'patternProperties': {
- r'packages': {
- 'type': 'object',
- 'default': {},
- 'additionalProperties': False,
- 'patternProperties': {
- r'\w[\w-]*': { # package name
- 'type': 'object',
- 'default': {},
- 'additionalProperties': False,
- 'properties': {
- 'version': {
- 'type': 'array',
- 'default': [],
- # version strings
- 'items': {'anyOf': [{'type': 'string'},
- {'type': 'number'}]}},
- 'compiler': {
- 'type': 'array',
- 'default': [],
- 'items': {'type': 'string'}}, # compiler specs
- 'buildable': {
- 'type': 'boolean',
- 'default': True,
- },
- 'permissions': {
- 'type': 'object',
- 'additionalProperties': False,
- 'properties': {
- 'read': {
- 'type': 'string',
- 'enum': ['user', 'group', 'world'],
- },
- 'write': {
- 'type': 'string',
- 'enum': ['user', 'group', 'world'],
- },
- 'group': {
- 'type': 'string',
- },
+#: Properties for inclusion in other schemas
+properties = {
+ 'packages': {
+ 'type': 'object',
+ 'default': {},
+ 'additionalProperties': False,
+ 'patternProperties': {
+ r'\w[\w-]*': { # package name
+ 'type': 'object',
+ 'default': {},
+ 'additionalProperties': False,
+ 'properties': {
+ 'version': {
+ 'type': 'array',
+ 'default': [],
+ # version strings
+ 'items': {'anyOf': [{'type': 'string'},
+ {'type': 'number'}]}},
+ 'compiler': {
+ 'type': 'array',
+ 'default': [],
+ 'items': {'type': 'string'}}, # compiler specs
+ 'buildable': {
+ 'type': 'boolean',
+ 'default': True,
+ },
+ 'permissions': {
+ 'type': 'object',
+ 'additionalProperties': False,
+ 'properties': {
+ 'read': {
+ 'type': 'string',
+ 'enum': ['user', 'group', 'world'],
+ },
+ 'write': {
+ 'type': 'string',
+ 'enum': ['user', 'group', 'world'],
+ },
+ 'group': {
+ 'type': 'string',
},
- },
- 'modules': {
- 'type': 'object',
- 'default': {},
- },
- 'providers': {
- 'type': 'object',
- 'default': {},
- 'additionalProperties': False,
- 'patternProperties': {
- r'\w[\w-]*': {
- 'type': 'array',
- 'default': [],
- 'items': {'type': 'string'}, }, }, },
- 'paths': {
- 'type': 'object',
- 'default': {},
- },
- 'variants': {
- 'oneOf': [
- {'type': 'string'},
- {'type': 'array',
- 'items': {'type': 'string'}}],
},
},
+ 'modules': {
+ 'type': 'object',
+ 'default': {},
+ },
+ 'providers': {
+ 'type': 'object',
+ 'default': {},
+ 'additionalProperties': False,
+ 'patternProperties': {
+ r'\w[\w-]*': {
+ 'type': 'array',
+ 'default': [],
+ 'items': {'type': 'string'}, }, }, },
+ 'paths': {
+ 'type': 'object',
+ 'default': {},
+ },
+ 'variants': {
+ 'oneOf': [
+ {'type': 'string'},
+ {'type': 'array',
+ 'items': {'type': 'string'}}],
+ },
},
},
},
},
}
+
+
+#: Full schema with metadata
+schema = {
+ '$schema': 'http://json-schema.org/schema#',
+ 'title': 'Spack package configuration file schema',
+ 'type': 'object',
+ 'additionalProperties': False,
+ 'properties': properties,
+}
diff --git a/lib/spack/spack/schema/repos.py b/lib/spack/spack/schema/repos.py
index fc5e5a4276..1ee0457d99 100644
--- a/lib/spack/spack/schema/repos.py
+++ b/lib/spack/spack/schema/repos.py
@@ -10,17 +10,21 @@
"""
+#: Properties for inclusion in other schemas
+properties = {
+ 'repos': {
+ 'type': 'array',
+ 'default': [],
+ 'items': {'type': 'string'},
+ },
+}
+
+
+#: Full schema with metadata
schema = {
'$schema': 'http://json-schema.org/schema#',
'title': 'Spack repository configuration file schema',
'type': 'object',
'additionalProperties': False,
- 'patternProperties': {
- r'repos': {
- 'type': 'array',
- 'default': [],
- 'items': {
- 'type': 'string'},
- },
- },
+ 'properties': properties,
}
diff --git a/lib/spack/spack/test/config.py b/lib/spack/spack/test/config.py
index ea725473cb..3f58a9c799 100644
--- a/lib/spack/spack/test/config.py
+++ b/lib/spack/spack/test/config.py
@@ -7,6 +7,7 @@ import os
import collections
import getpass
import tempfile
+from six import StringIO
from llnl.util.filesystem import touch, mkdirp
@@ -15,6 +16,12 @@ import ruamel.yaml as yaml
import spack.paths
import spack.config
+import spack.schema.compilers
+import spack.schema.config
+import spack.schema.packages
+import spack.schema.mirrors
+import spack.schema.repos
+import spack.util.spack_yaml as syaml
from spack.util.path import canonicalize_path
@@ -631,7 +638,7 @@ config:
spack.config._add_command_line_scopes(mutable_config, [str(tmpdir)])
-def test_immuntable_scope(tmpdir):
+def test_immutable_scope(tmpdir):
config_yaml = str(tmpdir.join('config.yaml'))
with open(config_yaml, 'w') as f:
f.write("""\
@@ -645,3 +652,58 @@ config:
with pytest.raises(spack.config.ConfigError):
scope.write_section('config')
+
+
+def check_schema(name, file_contents):
+ """Check a Spack YAML schema against some data"""
+ f = StringIO(file_contents)
+ data = syaml.load(f)
+ spack.config._validate(data, name)
+
+
+def test_bad_config_yaml(tmpdir):
+ with pytest.raises(spack.config.ConfigFormatError):
+ check_schema(spack.schema.config.schema, """\
+config:
+ verify_ssl: False
+ module_roots:
+ fmod: /some/fake/location
+""")
+
+
+def test_bad_mirrors_yaml(tmpdir):
+ with pytest.raises(spack.config.ConfigFormatError):
+ check_schema(spack.schema.mirrors.schema, """\
+mirrors:
+ local: True
+""")
+
+
+def test_bad_repos_yaml(tmpdir):
+ with pytest.raises(spack.config.ConfigFormatError):
+ check_schema(spack.schema.repos.schema, """\
+repos:
+ True
+""")
+
+
+def test_bad_compilers_yaml(tmpdir):
+ with pytest.raises(spack.config.ConfigFormatError):
+ check_schema(spack.schema.compilers.schema, """\
+compilers:
+ key_instead_of_list: 'value'
+""")
+
+ with pytest.raises(spack.config.ConfigFormatError):
+ check_schema(spack.schema.compilers.schema, """\
+compilers:
+ - shmompiler:
+ environment: /bad/value
+""")
+
+ with pytest.raises(spack.config.ConfigFormatError):
+ check_schema(spack.schema.compilers.schema, """\
+compilers:
+ - compiler:
+ fenfironfent: /bad/value
+""")