Dear c-level python specialists, Nested classes in python are really handy, and work pretty well, except for a bug in pickling:
Let's define a nested class: sage: class Bla: ....: class Ble: ....: pass ....: Let's fake Bla is defined in a module, not in the interpreter: sage: import __main__ sage: __main__.Bla = Bla Dumping an element of Bla works just fine: sage: x = Bla() sage: dumps(x) "x\x9ck`\xd2H\x8e\x8f\xcfM\xcc\xcc\x8b\x8f\xe7r\xcaI\xe4*d\xcc/d\xaa-dN\xd2\x03\x00v\xe3\x08'" But dumping an element of Bla.Ble breaks: sage: x = Bla.Ble() sage: dumps(x) --------------------------------------------------------------------------- PicklingError Traceback (most recent call last) /home/nthiery/.sage/temp/zephyr/23765/_home_nthiery__sage_init_sage_0.py in <module>() /opt/sage/local/lib/python2.5/site-packages/sage/structure/sage_object.so in sage.structure.sage_object.dumps (sage/structure/sage_object.c:5539)() PicklingError: Can't pickle __main__.Ble: attribute lookup __main__.Ble failed > /opt/sage-3.4.rc0/devel/sage-combinat/sage/sage_object.pyx(571)sage.structure.sage_object.dumps (sage/structure/sage_object.c:5539)() --------------------------------------------------------------------------- The reason behind this is twofold: First, the name of the class is improperly set: sage: Bla.Ble <class __main__.Ble at 0xb1e7c98c> sage: Bla.Ble.__name__ 'Ble' (which btw probably breaks other tools around) Well, let's work around this: sage: Bla.Ble.__name__ = "Bla.Ble" But then, a second problem: the code of cPickle (around line 1977) tries to lookup the attribute "Bla.Ble" in __main__, instead of successively looking up "Bla" in __main__, and then "Ble" in the result: sage: dumps(Bla.Ble) --------------------------------------------------------------------------- PicklingError Traceback (most recent call last) /home/nthiery/.sage/temp/zephyr/23765/_home_nthiery__sage_init_sage_0.py in <module>() /opt/sage/local/lib/python2.5/site-packages/sage/structure/sage_object.so in sage.structure.sage_object.dumps (sage/structure/sage_object.c:5539)() PicklingError: Can't pickle __main__.Bla.Ble: attribute lookup __main__.Bla.Ble failed > /opt/sage-3.4.rc0/devel/sage-combinat/sage/sage_object.pyx(571)sage.structure.sage_object.dumps (sage/structure/sage_object.c:5539)() It would take me a couple hours to learn the syntax to write c-code for python modules. Could any of the experts out there write me a 2-line patch upon cPickle:1977 to do the right thing (i.e. split __name__, and make the attribute lookup for each bit)? Just a draft will be fine; I am fine with reading and simple debuging. Thanks in advance! Best regards, Nicolas Here is the broken code: mod = PyImport_ImportModule(module_str); if (mod == NULL) { cPickle_ErrFormat(PicklingError, "Can't pickle %s: import of module %s " "failed", "OS", args, module); goto finally; } ############### HERE #################### klass = PyObject_GetAttrString(mod, name_str); if (klass == NULL) { cPickle_ErrFormat(PicklingError, "Can't pickle %s: attribute lookup %s.%s " "failed", "OSS", args, module, global_name); goto finally; } -- Nicolas M. ThiƩry "Isil" <nthi...@users.sf.net> http://Nicolas.Thiery.name/ --~--~---------~--~----~------------~-------~--~----~ To post to this group, send email to sage-devel@googlegroups.com To unsubscribe from this group, send email to sage-devel-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sage-devel URLs: http://www.sagemath.org -~----------~----~----~----~------~----~------~--~---