designateclient.warlock

Source code for designateclient.warlock

# Copyright 2012 Brian Waldon
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Code copied from Warlock, as warlock depends on jsonschema==0.2
# Hopefully we can upstream the changes ASAP.
#

import copy
import logging

import jsonschema
import six

LOG = logging.getLogger(__name__)


[docs]class InvalidOperation(RuntimeError): pass
[docs]class ValidationError(ValueError): pass
[docs]def model_factory(schema): """Generate a model class based on the provided JSON Schema :param schema: dict representing valid JSON schema """ schema = copy.deepcopy(schema) def validator(obj): """Apply a JSON schema to an object""" try: jsonschema.validate(obj, schema, cls=jsonschema.Draft3Validator) except jsonschema.ValidationError as e: raise ValidationError(str(e)) class Model(dict): """Self-validating model for arbitrary objects""" def __init__(self, *args, **kwargs): d = dict(*args, **kwargs) # we overload setattr so set this manually self.__dict__['validator'] = validator try: self.validator(d) except ValidationError as e: raise ValueError('Validation Error: %s' % str(e)) else: dict.__init__(self, d) self.__dict__['changes'] = {} def __getattr__(self, key): try: return self.__getitem__(key) except KeyError: raise AttributeError(key) def __setitem__(self, key, value): mutation = dict(self.items()) mutation[key] = value try: self.validator(mutation) except ValidationError as e: raise InvalidOperation(str(e)) dict.__setitem__(self, key, value) self.__dict__['changes'][key] = value def __setattr__(self, key, value): self.__setitem__(key, value) def clear(self): raise InvalidOperation() def pop(self, key, default=None): raise InvalidOperation() def popitem(self): raise InvalidOperation() def __delitem__(self, key): raise InvalidOperation() # NOTE(termie): This is kind of the opposite of what copy usually does def copy(self): return copy.deepcopy(dict(self)) def update(self, other): # NOTE(kiall): It seems update() doesn't update the # self.__dict__['changes'] dict correctly. mutation = dict(self.items()) mutation.update(other) try: self.validator(mutation) except ValidationError as e: raise InvalidOperation(str(e)) dict.update(self, other) def iteritems(self): return six.iteritems(copy.deepcopy(dict(self))) def items(self): return list(six.iteritems(copy.deepcopy(dict(self)))) def itervalues(self): return six.itervalues(copy.deepcopy(dict(self))) def keys(self): return list(six.iterkeys(copy.deepcopy(dict(self)))) def values(self): return list(six.itervalues(copy.deepcopy(dict(self)))) @property def changes(self): return copy.deepcopy(self.__dict__['changes']) Model.__name__ = str(schema['title']) return Model
Creative Commons Attribution 3.0 License

Except where otherwise noted, this document is licensed under Creative Commons Attribution 3.0 License. See all OpenStack Legal Documents.