summaryrefslogtreecommitdiff
path: root/warlock/core.py
diff options
context:
space:
mode:
Diffstat (limited to 'warlock/core.py')
-rw-r--r--warlock/core.py58
1 files changed, 46 insertions, 12 deletions
diff --git a/warlock/core.py b/warlock/core.py
index eacd7ab..ad3f3bd 100644
--- a/warlock/core.py
+++ b/warlock/core.py
@@ -27,16 +27,20 @@ def model_factory(schema):
except jsonschema.ValidationError:
raise ValidationError()
- class Model(object):
+ class Model(dict):
"""Self-validating model for arbitrary objects"""
- def __init__(self, **kwargs):
+
+ def __init__(self, *args, **kwargs):
+ d = dict(*args, **kwargs)
+
+ # we overload setattr so set this manually
self.__dict__['validator'] = validator
try:
- self.__dict__['validator'](kwargs)
+ self.validator(d)
except ValidationError:
raise ValueError()
else:
- self.__dict__['raw'] = kwargs
+ dict.__init__(self, d)
self.__dict__['changes'] = {}
@@ -46,27 +50,57 @@ def model_factory(schema):
except KeyError:
raise AttributeError(key)
- def __getitem__(self, key):
- return self.__dict__['raw'][key]
-
def __setitem__(self, key, value):
- mutation = copy.deepcopy(self.__dict__['raw'])
+ mutation = dict(self.items())
mutation[key] = value
try:
- self.__dict__['validator'](mutation)
+ self.validator(mutation)
except ValidationError:
raise InvalidOperation()
- self.__dict__['raw'] = mutation
+
+ 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):
+ mutation = dict(self.items())
+ mutation.update(other)
+ try:
+ self.validator(mutation)
+ except ValidationError:
+ raise InvalidOperation()
+ dict.update(self, other)
+
def iteritems(self):
- return copy.deepcopy(self.__dict__['raw']).iteritems()
+ return copy.deepcopy(dict(self)).iteritems()
def items(self):
- return copy.deepcopy(self.__dict__['raw']).items()
+ return copy.deepcopy(dict(self)).items()
+
+ def itervalues(self):
+ return copy.deepcopy(dict(self)).itervalues()
+
+ def values(self):
+ return copy.deepcopy(dict(self)).values()
@property
def changes(self):