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:
2017-09-19 13:43:48 +02:00
parent cfcaf96ac6
commit c8eec9fa9d
3 changed files with 132 additions and 0 deletions

View File

@@ -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