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 _______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope )