[Zope-dev] zc.relationship - can't pickle module objects

Martin Aspeli optilude+lists at gmail.com
Mon Mar 16 04:02:44 EDT 2009


Hi,

I *think* this is a bug in zc.relationship, but I'm not quite sure.

I'm using ZODB3 3.8.1 (to get BLOB support) and trying to install 
plone.app.relations, which depends on zc.relationship 1.0.2. In 
particular, it  subclasses zc.relationship.shared.Container, and stores 
a zc.relationship.index.Index object in self.relationIndex.

Now, the __init__ of zc.relationship.index.Index, which derives from 
Persistent, contains the code below. In self._relTools and and 
self._attrs, there are a pile of modules, types and functions being 
stored. I think these are causing the ZODB to barf. Interestingly, with 
whatever version of ZODB that comes with Zope 2.10 (3.7?), there's no 
problem.

Any ideas how to work around this, or even why it's a problem in one 
version of the ZODB but not another?

zc.relationship.index.Index's initialiser:

     def __init__(self, attrs, defaultTransitiveQueriesFactory=None,
                  dumpRel=generateToken, loadRel=resolveToken,
                  relFamily=IFBTree, deactivateSets=False):
         self._name_TO_mapping = OOBTree.OOBTree()
         # held mappings are objtoken to (relcount, relset)
         self._EMPTY_name_TO_relcount_relset = OOBTree.OOBTree()
         self._reltoken_name_TO_objtokenset = OOBTree.OOBTree()
         self.defaultTransitiveQueriesFactory = 
defaultTransitiveQueriesFactory
         self._relTools = getModuleTools(relFamily)
         self._relTools['load'] = loadRel
         self._relTools['dump'] = dumpRel
         self._relLength = Length.Length()
         self._relTokens = self._relTools['TreeSet']()
         self.deactivateSets = deactivateSets
         self._attrs = _attrs = {} # this is private, and it's not 
expected to
         # mutate after this initial setting.
         seen = set()
         for data in attrs:
             # see README.txt for description of attrs.
             if zope.interface.interfaces.IElement.providedBy(data):
                 data = {'element': data}
             res = getModuleTools(data.get('btree', IFBTree))
             res['element'] = val = data['element']
             res['attrname'] = val.__name__
             res['name'] = data.get('name', res['attrname'])
             if res['name'] in _attrs or val in seen:
                 raise ValueError('Duplicate in attrs', name, val)
             seen.add(val)
             _attrs[res['name']] = res
             res['dump'] = data.get('dump', generateToken)
             res['load'] = data.get('load', resolveToken)
             if (res['dump'] is None) ^ (res['load'] is None):
                 raise ValueError(
                     "either both of 'dump' and 'load' must be None, or 
neither")
                 # when both load and dump are None, this is a small
                 # optimization that can be a large optimization if the 
returned
                 # value is one of the main four options of the selected 
btree
                 # family (BTree, TreeSet, Set, Bucket).
             res['interface'] = val.interface
             res['multiple'] = data.get('multiple', False)
             res['call'] = zope.interface.interfaces.IMethod.providedBy(val)
             if res['TreeSet'].__name__.startswith('I'):
                 Mapping = IOBTree.IOBTree
             else:
                 assert res['TreeSet'].__name__.startswith('O')
                 Mapping = OOBTree.OOBTree
             self._name_TO_mapping[res['name']] = Mapping()
             # these are objtoken to (relcount, relset)

Regards,
Martin

-- 
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book



More information about the Zope-Dev mailing list