#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:18 saraedum]:
 > I don't think that's really what happens. Maybe I misunderstand what you
 are saying but I don't think that all objects in the pickle are
 instantiated and then all objects' `__setstate__` is called.

 Not all objects. Just all objects that are involved making the relevant
 `__setstate__` call. And of course this has to happen, otherwise there are
 no objects to pass.

 > Have a look at the example I posted above. There, to unpickle `b`, `a`
 is created, its `__setstate__` is called (which fails), and only then `b`
 is created and its `__setstate__` is called.
 >
 > > > There is of course lots of space for improvement, but what do you
 think about this idea?
 > > I think it's a bad idea because it doesn't solve the problem where it
 needs to be solved. Homsets fundamentally need domain and codomain for
 their construction. It's part of their hash. If a parent wants to include
 a homset in its construction parameter rather than in the `__setstate__`
 then it is introducing an unavoidable cycle.
 > This is not what happens. Here is a real-world example:
 > {{{
 > ...
 > sage: pickle.dumps(H)
 > AssertionError
 > }}}
 That is indeed puzzling. Would python `pickle` be unnecessarily strict
 compared to `cPickle`? It seems to me that `cPickle` produces a perfectly
 workable pickle from this:
 {{{
 sage: p=dumps(H)
 sage: explain_pickle(p)
 pg_Hom = unpickle_global('sage.categories.homset', 'Hom')
 pg_A = unpickle_global('__main__', 'A')
 pg = unpickle_instantiate(pg_A, ())
 pg_unreduce = unpickle_global('sage.structure.unique_representation',
 'unreduce')
 pg_Sets = unpickle_global('sage.categories.sets_cat', 'Sets')
 si = pg_unreduce(pg_Sets, (), {})
 unpickle_build(pg, pg_Hom(pg, pg, si, False))
 pg_Hom(pg, pg, si, False)
 }}}
 Also for your earlier example, it looks like the pickle produced by dumps
 should be just fine:
 {{{
 sage: explain_pickle(dumps(b))
 pg_B = unpickle_global('__main__', 'B')
 pg_A = unpickle_global('__main__', 'A')
 pg = unpickle_instantiate(pg_A, ())
 unpickle_build(pg, {'b':pg_B(pg)})
 pg_B(pg)
 sage: explain_pickle(dumps(b.a))
 pg_A = unpickle_global('__main__', 'A')
 pg = unpickle_instantiate(pg_A, ())
 pg_B = unpickle_global('__main__', 'B')
 unpickle_build(pg, {'b':pg_B(pg)})
 pg
 }}}
 > That's what happens above and does not work. I'm also confused because I
 always assumed that it would be enough to break the circularity on the
 first parameter in a single place. Somehow this does not seem to work.

 Well -- it does not work in the sense that `pickle.dumps` raises an
 AssertionError. Since that defaults to protocol 0, while sage has already
 settled on protocol 2, it's not an entirely fair test. However, specifying
 `protocol=2` doesn't help, so it's really a problem in pickle and possibly
 also in cPickle. However, the code produced by `explain_pickle` seems sane
 and that is directly interpreted from the produced pickle, so it could
 well be that cPickle does perform as we hope.

 I did a quick search on whether this is a known problem, but I didn't find
 compelling evidence. Closest was
 [http://bytes.com/topic/python/answers/37656-assertionerror-pickles-
 memoize-function this discussion]

--
Ticket URL: <http://trac.sagemath.org/ticket/15156#comment:19>
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.

Reply via email to