mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Fix bug in 'Attribute-with-hidden-object' deserializer
This commit is contained in:
parent
f8e29f6f10
commit
ff877b9671
2 changed files with 64 additions and 8 deletions
|
|
@ -23,7 +23,7 @@ from collections import deque, OrderedDict, defaultdict
|
|||
from collections.abc import MutableSequence, MutableSet, MutableMapping
|
||||
|
||||
try:
|
||||
from pickle import dumps, loads
|
||||
from pickle import dumps, loads, UnpicklingError
|
||||
except ImportError:
|
||||
from pickle import dumps, loads
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
|
@ -633,12 +633,12 @@ def to_pickle(data):
|
|||
# not one of the base types
|
||||
if hasattr(item, "__serialize_dbobjs__"):
|
||||
# Allows custom serialization of any dbobjects embedded in
|
||||
# the item that Evennia will otherwise not found (these would
|
||||
# the item that Evennia will otherwise not find (these would
|
||||
# otherwise lead to an error). Use the dbserialize helper from
|
||||
# this method.
|
||||
try:
|
||||
item.__serialize_dbobjs__()
|
||||
except TypeError:
|
||||
except TypeError as err:
|
||||
# we catch typerrors so we can handle both classes (requiring
|
||||
# classmethods) and instances
|
||||
pass
|
||||
|
|
@ -725,9 +725,13 @@ def from_pickle(data, db_obj=None):
|
|||
# use the dbunserialize helper in this module.
|
||||
try:
|
||||
item.__deserialize_dbobjs__()
|
||||
except TypeError:
|
||||
except (TypeError, UnpicklingError):
|
||||
# handle recoveries both of classes (requiring classmethods
|
||||
# or instances
|
||||
# or instances. Unpickling errors can happen when re-loading the
|
||||
# data from cache (because the hidden entity was already
|
||||
# deserialized and stored back on the object, unpickling it
|
||||
# again fails). TODO: Maybe one could avoid this retry in a
|
||||
# more graceful way?
|
||||
pass
|
||||
|
||||
return item
|
||||
|
|
|
|||
|
|
@ -15,9 +15,7 @@ class TestDbSerialize(TestCase):
|
|||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.obj = DefaultObject(
|
||||
db_key="Tester",
|
||||
)
|
||||
self.obj = DefaultObject(db_key="Tester")
|
||||
self.obj.save()
|
||||
|
||||
def test_constants(self):
|
||||
|
|
@ -117,3 +115,57 @@ class TestDbSerialize(TestCase):
|
|||
self.assertEqual(self.obj.db.test, {"a": [1, 2, 3]})
|
||||
self.obj.db.test |= {"b": [5, 6]}
|
||||
self.assertEqual(self.obj.db.test, {"a": [1, 2, 3], "b": [5, 6]})
|
||||
|
||||
|
||||
class _InvalidContainer:
|
||||
"""Container not saveable in Attribute (if obj is dbobj, it 'hides' it)"""
|
||||
def __init__(self, obj):
|
||||
self.hidden_obj = obj
|
||||
|
||||
|
||||
class _ValidContainer(_InvalidContainer):
|
||||
"""Container possible to save in Attribute (handles hidden dbobj explicitly)"""
|
||||
def __serialize_dbobjs__(self):
|
||||
self.hidden_obj = dbserialize.dbserialize(self.hidden_obj)
|
||||
def __deserialize_dbobjs__(self):
|
||||
self.hidden_obj = dbserialize.dbunserialize(self.hidden_obj)
|
||||
|
||||
|
||||
class DbObjWrappers(TestCase):
|
||||
"""
|
||||
Test the `__serialize_dbobjs__` and `__deserialize_dbobjs__` methods.
|
||||
|
||||
"""
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.dbobj1 = DefaultObject(db_key="Tester1")
|
||||
self.dbobj1.save()
|
||||
self.dbobj2 = DefaultObject(db_key="Tester2")
|
||||
self.dbobj2.save()
|
||||
|
||||
def test_dbobj_hidden_obj__fail(self):
|
||||
with self.assertRaises(TypeError):
|
||||
self.dbobj1.db.testarg = _InvalidContainer(self.dbobj1)
|
||||
|
||||
def test_consecutive_fetch(self):
|
||||
con =_ValidContainer(self.dbobj2)
|
||||
self.dbobj1.db.testarg = con
|
||||
attrobj = self.dbobj1.attributes.get("testarg", return_obj=True)
|
||||
|
||||
self.assertEqual(attrobj.value, con)
|
||||
self.assertEqual(attrobj.value, con)
|
||||
self.assertEqual(attrobj.value.hidden_obj, self.dbobj2)
|
||||
|
||||
def test_dbobj_hidden_obj__success(self):
|
||||
con =_ValidContainer(self.dbobj2)
|
||||
self.dbobj1.db.testarg = con
|
||||
|
||||
# accessing the same data twice
|
||||
res1 = self.dbobj1.db.testarg
|
||||
res2 = self.dbobj1.db.testarg
|
||||
|
||||
self.assertEqual(res1, res2)
|
||||
self.assertEqual(res1, con)
|
||||
self.assertEqual(res2, con)
|
||||
self.assertEqual(res1.hidden_obj, self.dbobj2)
|
||||
self.assertEqual(res2.hidden_obj, self.dbobj2)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue