summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Willhaus <mail@janwillhaus.de>2019-12-14 01:21:07 +0100
committerJan Willhaus <mail@janwillhaus.de>2019-12-14 01:35:34 +0100
commit2a053272ead21e8a4d2a41bda7362c01567b4492 (patch)
treeae3515d1c0faec57303a49d2854bb5c77cb9c27c
parent303d9a52a7837b49162445a6220989c9373aea88 (diff)
downloadwarlock-overhaul_of_model_class.tar.gz
Initial overhaul of the Model classoverhaul_of_model_class
-rw-r--r--tests/test_core.py32
-rw-r--r--warlock/model.py58
2 files changed, 46 insertions, 44 deletions
diff --git a/tests/test_core.py b/tests/test_core.py
index bc36c92..7623e7d 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -16,7 +16,6 @@ import copy
import json
import os
import unittest
-import warnings
import warlock
@@ -140,13 +139,16 @@ class TestCore(unittest.TestCase):
mike_3_sub["foo"] = "james"
self.assertEqual("mike", mike.sub["foo"])
- def test_forbidden_methods(self):
+ def test_previously_forbidden_methods(self):
Country = warlock.model_factory(fixture)
sweden = Country(name="Sweden", population=9379116)
- exc = warlock.InvalidOperation
- self.assertRaises(exc, sweden.clear)
- self.assertRaises(exc, sweden.pop, 0)
- self.assertRaises(exc, sweden.popitem)
+ sweden.clear()
+ self.assertDictEqual(sweden, {})
+ sweden = Country(name="Sweden", population=9379116)
+ self.assertEqual(sweden.pop("population"), 9379116)
+ self.assertEqual(sweden, {"name": "Sweden"})
+ self.assertEqual(sweden.popitem(), ("name", "Sweden"))
+ self.assertEqual(sweden, {})
def test_dict_syntax(self):
Country = warlock.model_factory(fixture)
@@ -168,24 +170,6 @@ class TestCore(unittest.TestCase):
delattr(sweden, "name")
self.assertRaises(AttributeError, getattr, sweden, "name")
- def test_changes(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name="Sweden", population=9379116)
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter("always")
- self.assertEqual(sweden.changes, {})
- assert w[0].category == DeprecationWarning
- sweden["name"] = "Finland"
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter("always")
- self.assertEqual(sweden.changes, {"name": "Finland"})
- assert w[0].category == DeprecationWarning
- sweden["name"] = "Norway"
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter("always")
- self.assertEqual(sweden.changes, {"name": "Norway"})
- assert w[0].category == DeprecationWarning
-
def test_patch_no_changes(self):
Country = warlock.model_factory(fixture)
sweden = Country(name="Sweden", population=9379116)
diff --git a/warlock/model.py b/warlock/model.py
index 62eb330..0dafab6 100644
--- a/warlock/model.py
+++ b/warlock/model.py
@@ -15,7 +15,6 @@
"""Self-validating model for arbitrary objects"""
import copy
-import warnings
import jsonpatch
import jsonschema
@@ -35,7 +34,6 @@ class Model(dict):
else:
dict.__init__(self, d)
- self.__dict__["changes"] = {}
self.__dict__["__original__"] = copy.deepcopy(d)
def __setitem__(self, key, value):
@@ -44,21 +42,19 @@ class Model(dict):
try:
self.validate(mutation)
except exceptions.ValidationError as exc:
- msg = "Unable to set '%s' to %r. Reason: %s" % (key, value, str(exc))
+ msg = "Unable to set '%s' to %r. Reason: %s" % (key, value, exc)
raise exceptions.InvalidOperation(msg)
dict.__setitem__(self, key, value)
- self.__dict__["changes"][key] = value
-
def __delitem__(self, key):
mutation = dict(self.items())
del mutation[key]
try:
self.validate(mutation)
except exceptions.ValidationError as exc:
- msg = "Unable to delete attribute '%s'. Reason: %s" % (key, str(exc))
- raise exceptions.InvalidOperation(msg)
+ msg = "Unable to delete attribute '%s'. Reason: %s" % (key, exc)
+ raise exceptions.InvalidOperation(msg) from exc
dict.__delitem__(self, key)
@@ -77,13 +73,40 @@ class Model(dict):
# BEGIN dict compatibility methods
def clear(self):
- raise exceptions.InvalidOperation()
-
- def pop(self, key, default=None):
- raise exceptions.InvalidOperation()
+ mutation = dict(self.items())
+ keys = list(mutation.keys())
+ for key in keys:
+ del mutation[key]
+ try:
+ self.validate(mutation)
+ except exceptions.ValidationError as exc:
+ msg = "Unable to clear data. Reason: %s" % (exc,)
+ raise exceptions.InvalidOperation(msg)
+ for key in keys:
+ del self[key]
+
+ def pop(self, key, *args):
+ try:
+ value = self.__getitem__(key)
+ self.__delitem__(key)
+ except KeyError:
+ if args:
+ return args[0]
+ raise
+ except exceptions.InvalidOperation as exc:
+ msg = "Unable to pop '%s'. Reason: %s" % (key, exc.__context__)
+ raise exceptions.InvalidOperation(msg)
+ return value
def popitem(self):
- raise exceptions.InvalidOperation()
+ item = next(iter(self.items()))
+ key = item[0]
+ try:
+ self.__delitem__(key)
+ except exceptions.InvalidOperation as exc:
+ msg = "Unable to pop next item '%s'. Reason: %s" % (item, exc.__context__)
+ raise exceptions.InvalidOperation(msg)
+ return item
def copy(self):
return copy.deepcopy(dict(self))
@@ -117,15 +140,10 @@ class Model(dict):
original = self.__dict__["__original__"]
return jsonpatch.make_patch(original, dict(self)).to_string()
- @property
- def changes(self):
- """Dumber version of 'patch' method"""
- deprecation_msg = "Model.changes will be removed in warlock v2"
- warnings.warn(deprecation_msg, DeprecationWarning, stacklevel=2)
- return copy.deepcopy(self.__dict__["changes"])
-
- def validate(self, obj):
+ def validate(self, obj=None):
"""Apply a JSON schema to an object"""
+ if obj is None:
+ obj = self
try:
if self.resolver is not None:
jsonschema.validate(obj, self.schema, resolver=self.resolver)