• Sebastien Robin's avatar
    ERP5Type: avoid PicklingError with ERP5 broken objects · 5abbc5a7
    Sebastien Robin authored
    Following code, with foo having portal type Foo which is
    not installed yet (thus it is broken) :
    connection = self.getConnection(portal)
    foo = connection.importFile(file_obj) => this does a savepoint
    foo._p_changed = 1
    
    Then next savepoint was raising :
    PicklingError: Can't pickle <class 'erp5.portal_type.Foo'>: it's not the same object as erp5.portal_type.Foo )
    
    This was because we had :
    foo.__class__.mro() : (<class 'erp5.portal_type.Foo'>, <class 'ZODB.broken.PersistentBroken'>,
     <class 'ZODB.broken.Broken'>, <type 'persistent.Persistent'>, <class 'erp5.portal_type.Foo'>,
     <class 'Products.ERP5Type.dynamic.lazy_class.GhostBase'>,
     <class 'Products.ERP5Type.dynamic.lazy_class.ERP5BaseBroken'>, <class 'Products.ERP5Type.Base.Base'>, *TAIL)
    
    and
    
    erp5.portal_type.__getattribute__("Foo").mro() :
    (<class 'erp5.portal_type.Foo'>, <class 'Products.ERP5Type.dynamic.lazy_class.ERP5BaseBroken'>,
      <class 'ZODB.broken.Broken'>, <class 'Products.ERP5Type.Base.Base'>, *TAIL)
    
    Classes where different because new class with new inheritance was created by
    ZODB.serialize.ObjecReader.load_persistent which does :
    
    if issubclass(klass, Broken):
        # We got a broken class. We might need to make it
        # PersistentBroken
        if not issubclass(klass, broken.PersistentBroken):
            klass = broken.persistentBroken(klass)
    
    Since ERP5BaseBroken is patched to mostly be like a PersistentBroken,
    make sure we allow serialization to identify ERP5BaseBroken as a
    PersistenBroken class.
    5abbc5a7
lazy_class.py 13.6 KB