Added pickle support for Resource classes, albeit a bit hacky.
Unpickling requires the class to be known, so we can't simply use to_dict() to pickle and pass the dict to __init__() to unpickle. This works for the pickled object itself (as pickle restores its type), but fails to restore the class of subobjects, such as some_node.picture. This is why the code now pickles each subobject too.
This commit is contained in:
@@ -140,6 +140,53 @@ class Resource(object):
|
||||
|
||||
return cls(dict_or_resource)
|
||||
|
||||
def __getstate__(self):
|
||||
"""Returns a state suitable for pickling.
|
||||
|
||||
This is basically a copy of to_dict(), except that subobjects
|
||||
are pickled instead of stored as sub-dict.
|
||||
"""
|
||||
import pickle
|
||||
|
||||
def parse_object(value):
|
||||
if isinstance(value, Resource):
|
||||
return '__pickled__', pickle.dumps(value)
|
||||
elif isinstance(value, list):
|
||||
new_list = []
|
||||
for obj in value:
|
||||
new_list.append(parse_object(obj))
|
||||
return new_list
|
||||
else:
|
||||
return value
|
||||
|
||||
data = {}
|
||||
for key in self.__data__:
|
||||
data[key] = parse_object(self.__data__[key])
|
||||
return data
|
||||
|
||||
def __setstate__(self, state):
|
||||
import pickle
|
||||
|
||||
def is_pickled(subval):
|
||||
return (isinstance(subval, tuple)
|
||||
and len(subval) == 2
|
||||
and subval[0] == '__pickled__'
|
||||
and isinstance(subval[1], bytes))
|
||||
|
||||
for key, val in state.items():
|
||||
if is_pickled(val):
|
||||
state[key] = pickle.loads(val[1])
|
||||
elif isinstance(val, list):
|
||||
for idx, subval in enumerate(val):
|
||||
if is_pickled(subval):
|
||||
val[idx] = pickle.loads(subval[1])
|
||||
elif isinstance(val, dict):
|
||||
for subkey, subval in val.items():
|
||||
if is_pickled(subval):
|
||||
val[subkey] = pickle.loads(subval[1])
|
||||
|
||||
self.__init__(state)
|
||||
|
||||
|
||||
class Find(Resource):
|
||||
@classmethod
|
||||
|
||||
Reference in New Issue
Block a user