#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 nbruin):
Replying to [comment:14 saraedum]:
> cPickle gets things wrong if any circularity is created in the first
parameter returned by `__reduce__`.
I think that is more appropriately phrased as "the pickle protocol is not
defined when construction parameters have circularities". You'd basically
be asking for a `__new__` call to have an argument that includes the to-
be-instantiated object. The pickle protocol has a way of introducing
circularities: via the `__getstate__` and `__setstate__` routines (i.e.,
the second return value of `__reduce__`).
> Consider the following code, which creates two objects which reference
each other:
> {{{
> class A(object):
> def __reduce__(self):
> return A,(),{'b':self.b}
> class B(object):
> def __init__(self,a):
> self.a = a
> def __reduce__(self):
> return B,(self.a,)
> b=B(A())
> b.a.b = b
> }}}
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.
> This is in particular a problem with Homsets. The `__reduce__` of Hom
does:
> {{{
> return Hom, (self._domain, self._codomain, self.__category, False)
> }}}
> Often the domain or codomain reference back to the Homset somehow.
Domain and codomain cannot possibly refer to the homset in their `__new__`
call. This is state later introduced, so domain and codomain, if they want
to put references in to homsets they should do so in the `__setstate__`
phase.
> 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. They can't
possibly have done that when they were originally created either!
We've see problems before where `__setstate__` values (e.g., python class
attributes stored in `__dict__` and pickled by default) were needed for
hash and equality, and the circularities arose on keys in to-be-
reconstructed dictionaries. Then `__hash__` can be requested on an object
that hasn't completed its `__setstate__` yet and see `__hash__` fail.
However, I can't see how homsets can affect the hash of `domain` and
`codomain`, so that problem shouldn't arise here.
--
Ticket URL: <http://trac.sagemath.org/ticket/15156#comment:15>
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.