-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathschema.py
More file actions
60 lines (48 loc) · 2.45 KB
/
schema.py
File metadata and controls
60 lines (48 loc) · 2.45 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
"""This module holds schema definitions for validating the various :py:class:`dicts` that make up parts of a
template, and also the helper functions necessary to validate an object against their respective schema.
"""
import json
import numpy as np
from jsonschema import validators, Draft4Validator, FormatChecker, ValidationError
from pkg_resources import resource_filename
# helper function that will later be used to tell the schema validator how to validate objects of type "array"
def is_array(checker, instance):
return isinstance(instance, (list, np.ndarray))
# Extend the default type checker by redefining "array"
# whenever a schema expects a value of type "array", it will now use the is_array function to check if the value is acceptable.
custom_type_checker = Draft4Validator.TYPE_CHECKER.redefine("array", is_array)
# Create a custom validator that uses the new type checker.
# any validation performed with CustomValidator will use the custom array checker
CustomValidator = validators.extend(Draft4Validator, type_checker=custom_type_checker)
format_checker = FormatChecker()
# Define a custom format checker
# called when a JSON schema specifies that a value should have the format "datatype"
@format_checker.checks('datatype')
def is_python_datatype(value):
"""Return whether the given value is a valid data type specification for a NetCDF variable"""
if isinstance(value, np.dtype):
return True
if isinstance(value, type):
return issubclass(value, np.number)
return False
# Load JSON schema file
TEMPLATE_SCHEMA_JSON = resource_filename(__name__, 'template_schema.json')
with open(TEMPLATE_SCHEMA_JSON) as f:
TEMPLATE_SCHEMA = json.load(f)
# Use the custom validator to check it is valid according to Draft 4 rules
CustomValidator.check_schema(TEMPLATE_SCHEMA)
# ready-to-use validator that applies both custom type and format checks
template_validator = CustomValidator(TEMPLATE_SCHEMA, format_checker=format_checker)
# Validation checks
def validate_template(t):
template_validator.validate(t)
def validate_dimensions(d):
validate_template({'_dimensions': d})
def validate_variables(v):
validate_template({'_variables': v})
def validate_global_attributes(a):
if hasattr(a, 'keys'):
special = [k for k in a.keys() if k.startswith('_')]
if special:
raise ValidationError('Special attributes {} not allowed in global attributes dict'.format(special))
template_validator.validate(a)