#15156: Pickling with __reduce__() loops creates invalid pickles
-------------------------------------+-------------------------------------
Reporter: vbraun | Owner:
Type: defect | Status: needs_info
Priority: major | Milestone: sage-6.3
Component: misc | Resolution:
Keywords: | Merged in:
Authors: SimonKing, | Reviewers:
jkeitel, novoselt, nbruin | Work issues:
Report Upstream: N/A | Commit:
Branch: | 82ba456b8c828700d28ac36822b300f00d8b1308
u/saraedum/ticket/15156 | Stopgaps:
Dependencies: #15692 |
-------------------------------------+-------------------------------------
Comment (by saraedum):
Replying to [comment:15 nbruin]:
> Replying to [comment:14 saraedum]:
> > Consider the following code, which creates two objects which reference
each other:
> > [...]
> Note that the circular reference wasn't put there in the corresponding
`__new__` call. It was a later change of state that caused the circularity
(this is always necessarily the case). So the circularity should be
recreated during the `__setstate__` phase of unpickling.
Right. But this is hard to do automatically.
> > I have no idea how to fix this. The domain is really needed here
because it determines the class of the result and it is used for a lookup
in a cache. Any ideas?
> Yes, domain and codomain are really part of a homset, so it's not
unreasonable to make them part of the `__new__` parameters. If
circularities arise here, then I'd say the domain and codomain are at
fault referencing a homset in their instantiation phase.
I'm not sure what you mean by "instantiation phase".
> They can't possibly have done that when they were originally created
either!
Sure. But when pickling you do not only want to restore the initial state
of an object but also to some extent the current state.
Here is an idea how to solve the problem with restoring the state. Say we
have `Hom(A,A)` and `A` somehow circles back to `Hom(A,A)` through its
state (e.g. its `__dict__`). The problem is that to unpickle `Hom(A,A)`,
`A` is created, `A`'s state is restored (which fails), and then `Hom(A,A)`
is created. What if `Hom(A,A)` took care of restoring the state of `A`
until `Hom(A,A)` exists?
I implemented a sketch of this idea and it at least solves this problem
for the cases that I had a look at. I changed `Hom`'s `__reduce__` to
{{{
args = (DelayedStatePickle(self._domain),
DelayedStatePickle(self._codomain), self.__category, False)
states = [a.inner_getstate() if isinstance(a,DelayedStatePickle) else None
for a in args]
return unpickle_from_DelayedStatePickles, (Hom, args), states
}}}
and make `__setstate__` set the state of domain and codomain:
{{{
for a,s in zip(self._args_delayed, states):
if s is not None:
a.__setstate__(s)
}}}
With
{{{
def unpickle_from_DelayedStatePickles(callable, args):
ret = callable(*args)
ret._args_delayed = args
return ret
class DelayedStatePickle(object):
def __init__(self, obj):
self.obj = obj
def inner_getstate(self):
reduction = self.obj.__reduce__()
assert all([r is None for r in reduction[3:]])
self.callable, self.args, self.state = reduction[:3]
return self.state
def __reduce__(self):
return self.callable, self.args
}}}
There is of course lots of space for improvement, but what do you think
about this idea?
--
Ticket URL: <http://trac.sagemath.org/ticket/15156#comment:16>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica,
and MATLAB
--
You received this message because you are subscribed to the Google Groups
"sage-trac" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac.
For more options, visit https://groups.google.com/d/optout.