new de/serialization logic
This commit is contained in:
parent
dbde966947
commit
f9b17d25d1
2 changed files with 115 additions and 55 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
Unit tests for typeclass base system
|
Unit tests for typeclass base system
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
from evennia.typeclasses import attributes
|
from evennia.typeclasses import attributes
|
||||||
from evennia.utils.test_resources import BaseEvenniaTest, EvenniaTestCase
|
from evennia.utils.test_resources import BaseEvenniaTest, EvenniaTestCase
|
||||||
|
|
@ -26,13 +27,24 @@ class TestAttributes(BaseEvenniaTest):
|
||||||
self.obj1.db.testattr = value
|
self.obj1.db.testattr = value
|
||||||
self.assertEqual(self.obj1.db.testattr, value)
|
self.assertEqual(self.obj1.db.testattr, value)
|
||||||
|
|
||||||
|
# "plain" subclasses
|
||||||
value = DictSubclass({"fo": "foo", "bar": "bar"})
|
value = DictSubclass({"fo": "foo", "bar": "bar"})
|
||||||
self.obj1.db.testattr = value
|
self.obj1.db.testattr = value
|
||||||
self.assertEqual(self.obj1.db.testattr, value)
|
self.assertEqual(self.obj1.db.testattr, value)
|
||||||
|
|
||||||
value = DictSubclass({"fo": "foo", "bar": "bar", "obj": self.obj2})
|
self.obj1.db.testattr["fo"] = "foo2"
|
||||||
self.obj1.db.testattr = value
|
value.update({"fo": "foo2"})
|
||||||
self.assertEqual(self.obj1.db.testattr, value)
|
self.assertEqual(self.obj1.db.testattr, value)
|
||||||
|
self.assertEqual(self.obj1.attributes.get("testattr"), value)
|
||||||
|
|
||||||
|
# nested subclasses
|
||||||
|
value = DictSubclass({"nested": True, "deep": DictSubclass({"fo": "foo", "bar": "bar"})})
|
||||||
|
self.obj1.db.testattr = value
|
||||||
|
|
||||||
|
self.obj1.db.testattr["deep"]["fo"] = "nemo"
|
||||||
|
value["deep"].update({"fo": "nemo"})
|
||||||
|
self.assertEqual(self.obj1.db.testattr, value)
|
||||||
|
self.assertEqual(self.obj1.attributes.get("testattr"), value)
|
||||||
|
|
||||||
@override_settings(TYPECLASS_AGGRESSIVE_CACHE=False)
|
@override_settings(TYPECLASS_AGGRESSIVE_CACHE=False)
|
||||||
@patch("evennia.typeclasses.attributes._TYPECLASS_AGGRESSIVE_CACHE", False)
|
@patch("evennia.typeclasses.attributes._TYPECLASS_AGGRESSIVE_CACHE", False)
|
||||||
|
|
@ -47,14 +59,25 @@ class TestAttributes(BaseEvenniaTest):
|
||||||
self.assertEqual(self.obj1.db.testattr, value)
|
self.assertEqual(self.obj1.db.testattr, value)
|
||||||
self.assertFalse(self.obj1.attributes.backend._cache)
|
self.assertFalse(self.obj1.attributes.backend._cache)
|
||||||
|
|
||||||
|
# "plain" subclasses
|
||||||
value = DictSubclass({"fo": "foo", "bar": "bar"})
|
value = DictSubclass({"fo": "foo", "bar": "bar"})
|
||||||
self.obj1.db.dict_subclass = value
|
self.obj1.db.testattr = value
|
||||||
self.assertEqual(self.obj1.db.dict_subclass, value)
|
self.assertEqual(self.obj1.db.testattr, value)
|
||||||
|
|
||||||
|
self.obj1.db.testattr["fo"] = "foo2"
|
||||||
|
value.update({"fo": "foo2"})
|
||||||
|
self.assertEqual(self.obj1.db.testattr, value)
|
||||||
|
self.assertEqual(self.obj1.attributes.get("testattr"), value)
|
||||||
self.assertFalse(self.obj1.attributes.backend._cache)
|
self.assertFalse(self.obj1.attributes.backend._cache)
|
||||||
|
|
||||||
value = DictSubclass({"fo": "foo", "bar": "bar", "obj": self.obj2})
|
# nested subclasses
|
||||||
self.obj1.db.dict_subclass = value
|
value = DictSubclass({"nested": True, "deep": DictSubclass({"fo": "foo", "bar": "bar"})})
|
||||||
self.assertEqual(self.obj1.db.dict_subclass, value)
|
self.obj1.db.testattr = value
|
||||||
|
|
||||||
|
self.obj1.db.testattr["deep"]["fo"] = "nemo"
|
||||||
|
value["deep"].update({"fo": "nemo"})
|
||||||
|
self.assertEqual(self.obj1.db.testattr, value)
|
||||||
|
self.assertEqual(self.obj1.attributes.get("testattr"), value)
|
||||||
self.assertFalse(self.obj1.attributes.backend._cache)
|
self.assertFalse(self.obj1.attributes.backend._cache)
|
||||||
|
|
||||||
def test_weird_text_save(self):
|
def test_weird_text_save(self):
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ class _SaverList(_SaverMutable, MutableSequence):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._data = list()
|
self._data = kwargs.pop("_class", list)()
|
||||||
|
|
||||||
@_save
|
@_save
|
||||||
def __iadd__(self, otherlist):
|
def __iadd__(self, otherlist):
|
||||||
|
|
@ -307,7 +307,7 @@ class _SaverDict(_SaverMutable, MutableMapping):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._data = dict()
|
self._data = kwargs.pop("_class", dict)()
|
||||||
|
|
||||||
def has_key(self, key):
|
def has_key(self, key):
|
||||||
return key in self._data
|
return key in self._data
|
||||||
|
|
@ -644,7 +644,8 @@ def to_pickle(data):
|
||||||
# classmethods) and instances
|
# classmethods) and instances
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if hasattr(item, "items"):
|
if hasattr(item, "__iter__"):
|
||||||
|
try:
|
||||||
# we try to conserve the iterable class, if not convert to dict
|
# we try to conserve the iterable class, if not convert to dict
|
||||||
try:
|
try:
|
||||||
return item.__class__(
|
return item.__class__(
|
||||||
|
|
@ -652,7 +653,7 @@ def to_pickle(data):
|
||||||
)
|
)
|
||||||
except (AttributeError, TypeError):
|
except (AttributeError, TypeError):
|
||||||
return {process_item(key): process_item(val) for key, val in item.items()}
|
return {process_item(key): process_item(val) for key, val in item.items()}
|
||||||
elif hasattr(item, "__iter__"):
|
except:
|
||||||
# we try to conserve the iterable class, if not convert to list
|
# we try to conserve the iterable class, if not convert to list
|
||||||
try:
|
try:
|
||||||
return item.__class__([process_item(val) for val in item])
|
return item.__class__([process_item(val) for val in item])
|
||||||
|
|
@ -720,7 +721,8 @@ def from_pickle(data, db_obj=None):
|
||||||
return OrderedDict((process_item(key), process_item(val)) for key, val in item.items())
|
return OrderedDict((process_item(key), process_item(val)) for key, val in item.items())
|
||||||
elif dtype == deque:
|
elif dtype == deque:
|
||||||
return deque(process_item(val) for val in item)
|
return deque(process_item(val) for val in item)
|
||||||
elif hasattr(item, "items"):
|
elif hasattr(item, "__iter__"):
|
||||||
|
try:
|
||||||
# we try to conserve the iterable class, if not convert to dict
|
# we try to conserve the iterable class, if not convert to dict
|
||||||
try:
|
try:
|
||||||
return item.__class__(
|
return item.__class__(
|
||||||
|
|
@ -728,7 +730,7 @@ def from_pickle(data, db_obj=None):
|
||||||
)
|
)
|
||||||
except (AttributeError, TypeError):
|
except (AttributeError, TypeError):
|
||||||
return {process_item(key): process_item(val) for key, val in item.items()}
|
return {process_item(key): process_item(val) for key, val in item.items()}
|
||||||
elif hasattr(item, "__iter__"):
|
except:
|
||||||
try:
|
try:
|
||||||
# we try to conserve the iterable class if
|
# we try to conserve the iterable class if
|
||||||
# it accepts an iterator
|
# it accepts an iterator
|
||||||
|
|
@ -794,23 +796,28 @@ def from_pickle(data, db_obj=None):
|
||||||
dat = _SaverDeque(_parent=parent)
|
dat = _SaverDeque(_parent=parent)
|
||||||
dat._data.extend(process_item(val) for val in item)
|
dat._data.extend(process_item(val) for val in item)
|
||||||
return dat
|
return dat
|
||||||
elif hasattr(item, "items"):
|
elif hasattr(item, "__iter__"):
|
||||||
|
try:
|
||||||
# we try to conserve the iterable class, if not convert to dict
|
# we try to conserve the iterable class, if not convert to dict
|
||||||
try:
|
try:
|
||||||
return item.__class__(
|
dat = _SaverDict(_parent=parent, _class=item.__class__)
|
||||||
(process_item(key), process_tree(val, parent)) for key, val in item.items()
|
dat._data.update(
|
||||||
|
(process_item(key), process_tree(val, dat)) for key, val in item.items()
|
||||||
)
|
)
|
||||||
|
return dat
|
||||||
except (AttributeError, TypeError):
|
except (AttributeError, TypeError):
|
||||||
dat = _SaverDict(_parent=parent)
|
dat = _SaverDict(_parent=parent)
|
||||||
dat._data.update(
|
dat._data.update(
|
||||||
(process_item(key), process_tree(val, dat)) for key, val in item.items()
|
(process_item(key), process_tree(val, dat)) for key, val in item.items()
|
||||||
)
|
)
|
||||||
return dat
|
return dat
|
||||||
elif hasattr(item, "__iter__"):
|
except:
|
||||||
try:
|
try:
|
||||||
# we try to conserve the iterable class if it
|
# we try to conserve the iterable class if it
|
||||||
# accepts an iterator
|
# accepts an iterator
|
||||||
return item.__class__(process_tree(val, parent) for val in item)
|
dat = _SaverList(_parent=parent, _class=item.__class__)
|
||||||
|
dat._data.extend(process_tree(val, dat) for val in item)
|
||||||
|
return dat
|
||||||
except (AttributeError, TypeError):
|
except (AttributeError, TypeError):
|
||||||
dat = _SaverList(_parent=parent)
|
dat = _SaverList(_parent=parent)
|
||||||
dat._data.extend(process_tree(val, dat) for val in item)
|
dat._data.extend(process_tree(val, dat) for val in item)
|
||||||
|
|
@ -828,7 +835,9 @@ def from_pickle(data, db_obj=None):
|
||||||
# convert lists, dicts and sets to their Saved* counterparts. It
|
# convert lists, dicts and sets to their Saved* counterparts. It
|
||||||
# is only relevant if the "root" is an iterable of the right type.
|
# is only relevant if the "root" is an iterable of the right type.
|
||||||
dtype = type(data)
|
dtype = type(data)
|
||||||
if dtype == list:
|
if dtype in (str, int, float, bool, bytes, SafeString, tuple):
|
||||||
|
return process_item(data)
|
||||||
|
elif dtype == list:
|
||||||
dat = _SaverList(_db_obj=db_obj)
|
dat = _SaverList(_db_obj=db_obj)
|
||||||
dat._data.extend(process_tree(val, dat) for val in data)
|
dat._data.extend(process_tree(val, dat) for val in data)
|
||||||
return dat
|
return dat
|
||||||
|
|
@ -858,6 +867,34 @@ def from_pickle(data, db_obj=None):
|
||||||
dat = _SaverDeque(_db_obj=db_obj)
|
dat = _SaverDeque(_db_obj=db_obj)
|
||||||
dat._data.extend(process_item(val) for val in data)
|
dat._data.extend(process_item(val) for val in data)
|
||||||
return dat
|
return dat
|
||||||
|
elif hasattr(data, "__iter__"):
|
||||||
|
try:
|
||||||
|
# we try to conserve the iterable class, if not convert to dict
|
||||||
|
try:
|
||||||
|
dat = _SaverDict(_db_obj=db_obj, _class=data.__class__)
|
||||||
|
dat._data.update(
|
||||||
|
(process_item(key), process_tree(val, dat)) for key, val in data.items()
|
||||||
|
)
|
||||||
|
return dat
|
||||||
|
except (AttributeError, TypeError):
|
||||||
|
dat = _SaverDict(_db_obj=db_obj)
|
||||||
|
dat._data.update(
|
||||||
|
(process_item(key), process_tree(val, dat)) for key, val in data.items()
|
||||||
|
)
|
||||||
|
return dat
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
# we try to conserve the iterable class if it
|
||||||
|
# accepts an iterator
|
||||||
|
dat = _SaverList(_db_obj=db_obj, _class=data.__class__)
|
||||||
|
dat._data.extend(process_tree(val, dat) for val in data)
|
||||||
|
return dat
|
||||||
|
|
||||||
|
except (AttributeError, TypeError):
|
||||||
|
dat = _SaverList(_db_obj=db_obj)
|
||||||
|
dat._data.extend(process_tree(val, dat) for val in data)
|
||||||
|
return dat
|
||||||
|
|
||||||
return process_item(data)
|
return process_item(data)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue