def get_validator(overwrite=False, normalizers=None, **kwargs): r"""Return the validator that includes ygg expansion types. Args: overwrite (bool, optional): If True, the existing validator will be overwritten. Defaults to False. normalizers (dict, optional): Additional normalizers to add. **kwargs: Additional keyword arguments are passed to normalizer.create. Returns: jsonschema.IValidator: JSON schema validator. """ from yggdrasil.metaschema import normalizer global _validator if (_validator is None) or overwrite: metaschema = get_metaschema() # Get set of validators all_validators = copy.deepcopy(_base_validator.VALIDATORS) for k, v in get_registered_properties().items(): if (not v._replaces_existing): assert (k not in all_validators) all_validators[k] = v.wrapped_validate # Get set of datatypes # TODO: This will need to be changed if back-ported in jsonschema if _jsonschema_ver_maj < 3: all_datatypes = copy.deepcopy(_base_validator.DEFAULT_TYPES) for k, v in get_registered_types().items(): if (not v._replaces_existing): # Error raised on registration assert (k not in all_datatypes) all_datatypes[k] = v.python_types kwargs['default_types'] = all_datatypes else: type_checker = copy.deepcopy(_base_validator.TYPE_CHECKER) new_type_checkers = {} for k, v in get_registered_types().items(): if (not v._replaces_existing): # Error raised on registration assert (k not in type_checker._type_checkers) new_type_checkers[k] = v.jsonschema_type_checker kwargs['type_checker'] = type_checker.redefine_many( new_type_checkers) # Get set of normalizers if normalizers is None: normalizers = {} # Use default base and update validators _validator = normalizer.create(meta_schema=metaschema, validators=all_validators, normalizers=normalizers, **kwargs) _validator._base_validator = _base_validator return _validator
def create_metaschema(overwrite=False): r"""Create the meta schema for validating ygg schema. Args: overwrite (bool, optional): If True, the existing meta schema will be overwritten. If False and the metaschema exists, an error will be raised. Defaults to False. Returns: dict: Meta schema specifying rules for ygg type schema. This includes all original JSON schema rules with the addition of types and property definitions. Raises: RuntimeError: If the file already exists and overwrite is False. """ if (not overwrite) and os.path.isfile(_metaschema_fname): raise RuntimeError("Metaschema file already exists.") out = copy.deepcopy(_base_validator.META_SCHEMA) out['title'] = "Ygg meta-schema for data type schemas" # Lower versions have a differing draft4 if _jsonschema_ver_maj < 3: for x in ['minItems', 'uniqueItems']: if x in out['properties']['enum']: del out['properties']['enum'][x] # TODO: Replace schema with a link to the metaschema in the documentation # del out['$schema'] # Add properties for k, v in get_registered_properties().items(): if v.schema is not None: assert (k not in out['properties']) out['properties'][k] = v.schema # Add types for k, v in sorted(get_registered_types().items()): if k not in out['definitions']['simpleTypes']['enum']: out['definitions']['simpleTypes']['enum'].append(k) for p in v.properties: assert (p in out['properties']) # Convert to unicode if python 2 if backwards.PY2: # pragma: Python 2 out = backwards.as_unicode(out, recurse=True, convert_types=(str, ), allow_pass=True) # Print print('Created metaschema') pprint.pprint(out) # Save it to a file with open(_metaschema_fname, 'w') as fd: encode_json(out, fd) return out
def test_get_registered_properties(): r"""Test get_registered_properties.""" assert (properties.get_registered_properties())
from yggdrasil.tests import (assert_raises, assert_equal, assert_not_equal) from yggdrasil.metaschema import properties, get_metaschema, _base_validator from yggdrasil.metaschema.properties.MetaschemaProperty import MetaschemaProperty existing = properties.get_registered_properties() non_existant = 'invalid_xyz123' existing_class = list(existing.keys())[0] existing_validator = non_existant assert (non_existant not in existing) assert (non_existant not in _base_validator.VALIDATORS) for k, v in _base_validator.VALIDATORS.items(): if k not in existing: existing_validator = k break else: # pragma: debug # Not sure how this would happen, but guarantee it dosn't do it silently raise Exception('Could not locate unregistered jsonschema property.') def test_register_metaschema_property(): r"""Test errors in register_metaschema_property.""" # Error when property class already registered args = ('ReplacementClassSchema', (MetaschemaProperty, ), { 'name': existing_class }) assert_raises(ValueError, type, *args) # Error when replacement class has schema args = ('ReplacementClassSchema', (MetaschemaProperty, ), { 'name': existing_validator, 'schema': {} })