Hi Burcin, > The error I get when I try to load the .sobj file linked above in > Sage-3.3 is: > > ... > /home/burcin/sage/sage-3.3/local/lib/python2.5/site-packages/sage/structure/sage_object.so > in sage.structure.sage_object.loads > (sage/structure/sage_object.c:6156)() > > RuntimeError: (None, <function PolynomialRing at 0x1355e60>, (Fraction > Field of Univariate Polynomial Ring in t over Finite Field of size 13, > 'T', None, False)) invalid data stream > invalid load key, 'x'. > Unable to load pickled data. >
Yep, this is the same error we had with the other pickles. This is a wildly uninformative error message, which I think I know enough to fix at this point (someone should file a ticket and assign it to me). All this error really means is that cPickle ran into an error trying to unpickle the object. In more detail: Both Pickle and cPickle keep a stream of arguments as they load an object, which is what gets stored in a pickle. They just run in a loop, that basically says: if there's anything left in the stream, pop off an argument, which is a key telling it what kind of object is next, dispatch to a method that knows how to recreate that object, pop the appropriate number of arguments off the stream, use those to reconstruct the object, and then loop. I'm pretty sure what's happening here is that a correct load key gets popped off the stream, and the attempt to reconstruct that part of the object fails, at which point the *key* is gone from the stream, but not all of the arguments, and the exception we raise gets caught, so the attempt to unpickle continues. However, now the stream has nonsense (specifically leftover arguments) at the front of it, so on the next loop, we see the "Invalid load key: 'x'" error. So all this error means is that something went wrong unpickling. Here's what's happening with Alex's 3.1.1 pickle. Actually, in the process of explaining what happens in this case, I've realized it's slightly more subtle than I thought (and in particular, some of these details should be added to the trac ticket). - The FractionField object Alex pickled in 3.1.1 was a pre-coercion FractionField. So it doesn't have _element_class and _element_constructor attributes, and it was created when FractionField had no __reduce__ method -- so it just calls __new__ on the class, and tries to start filling in the dict for the object. This goes fine, actually -- the FractionField unpickles okay. Keep in mind, though, that it's now an instance of the *new* FractionField class (i.e. one with the new coercion stuff in place) that happens to be missing some key attributes (like _element_class and _element_constructor -- which are set to None). - The next thing Alex's code tries to unpickle is a polynomial ring over the FractionField. This has always had a __reduce__ method, which stores a call to the PolynomialRing function in sage.rings.polynomial.polynomial_ring_constructor. - The polynomial ring constructor always creates a polynomial in the process of initializing, namely its generator. This is accomplished by calling self([0,1], is_gen=True), which ultimately calls [ R(z) for z in [0,1] ], where R is self.base_ring(). - Since self.base_ring() is the fraction field, we try to dispatch __call__ on that. Of course, the new FractionField class doesn't have a __call__ method -- that's in Parent now. So it goes up the class hierarchy and dispatches that __call__. - The first thing that method does is say "if self._element_constructor is None: raise NotImplementedError." This is the error we hit, because our 3.1.1 FractionField object has this set to None. Boom. This could explain why you didn't hit this in testing the new code -- did you create some polynomial rings over fraction fields with the old class, then try to unpickle them with the new one? I bet this would fail. > I don't have so much time to investigate this either, but if you > already found the cause then I could probably write a clean patch. Can > you explain how you managed to load the old files, or send your hackish > patch to me? > So that's a pretty longwinded explanation for what's happening. Now, the fix was easy: I commented out the two lines in Parent.__call__ which raise the NotImplementedError, and I copy-pasted the code for FractionField.__call__ back in place. This is clearly a hack. :) In fact, it's bad -- the new objects I create don't pickle correctly, or even if they did, we'd have the same problem trying to load them. However, they loaded their coefficients just fine -- so I'm going to write something that will instantiate correctly formed classes, coerce the old values over via lists, and then finally save the new, correctly structured objects. A mild pain, but it seems straightforward enough, and I didn't think of anything easier. Hopefully that makes sense -- but it's 2:30AM here, so feel free to write back and say "that didn't make any sense ... try again." :) -cc --~--~---------~--~----~------------~-------~--~----~ To post to this group, send email to sage-support@googlegroups.com To unsubscribe from this group, send email to sage-support-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sage-support URLs: http://www.sagemath.org -~----------~----~----~----~------~----~------~--~---