Opened 3 years ago

Last modified 2 years ago

#25491 new defect

Broken unpickling of nested bindable classes in corner case

Reported by: nthiery Owned by:
Priority: major Milestone: sage-8.3
Component: pickling Keywords:
Cc: Merged in:
Authors: Reviewers:
Report Upstream: N/A Work issues:
Branch: Commit:
Dependencies: Stopgaps:

Status badges

Description (last modified by nthiery)

Classes are pickled by name in Sage, and reconstructed as in this example upon unpickling:

sage: cls = unpickle_global('sage.categories.hopf_algebras_with_basis', 'HopfAlgebrasWithBasis.TensorProducts')

In practice, unpickle_global loads the module, and search for the full class name HopfAlgebrasWithBasis.TensorProducts in the dictionary of the module.

In the case of a nested class above which comes from a functorial construction, there currently are cases where, upon importing the module, the base class of the nested class has not yet been initialized, which leads to errors:

sage: cls(QQ)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
...
KeyError: 'HopfAlgebrasWithBasis.'

The initialization is indeed done upon accessing the class for the first time from its surrounding class:

    sage: HopfAlgebrasWithBasis.TensorProducts

Now everything works:

sage: cls is HopfAlgebrasWithBasis.TensorProducts
True
sage: cls(QQ)
Category of tensor products of hopf algebras with basis over Rational Field

Not sure what's the best way to proceed; forcing the unpickling to unpickle instead the base class HopfAlgebrasWithBasis, and then recover TensorProducts by a getattr ?

I'll add the original non-working example that was found by Pauline.

Change History (3)

comment:1 Changed 2 years ago by nthiery

Hmm, got hurt by this once again ... in a variant of the same use case.

comment:2 Changed 2 years ago by nthiery

After poking around a bit, I'd be tempted to customize the pickling so that a nested class foo.A.B would be unpickled as getattr(getattr(foo, "A"),"B"). This would however not resolve the unpickling of old pickles.

Last edited 2 years ago by nthiery (previous) (diff)

comment:3 Changed 2 years ago by nthiery

  • Description modified (diff)
Note: See TracTickets for help on using tickets.