relation: some minor changes; + __parent__ assignment for relation when registering it

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@668 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2005-11-09 11:21:56 +00:00
parent cb9dc6219f
commit 963a167f12
7 changed files with 64 additions and 29 deletions

View file

@ -1,6 +1,8 @@
Yet Another Relations (Reference) Engine... Yet Another Relations (Reference) Engine...
=========================================== ===========================================
($Id$)
>>> from zope.app.testing.placelesssetup import setUp >>> from zope.app.testing.placelesssetup import setUp
>>> setUp() >>> setUp()
@ -122,19 +124,31 @@ working with events).
>>> from zope.app import zapi >>> from zope.app import zapi
>>> relations = zapi.getUtility(IRelationsRegistry) >>> relations = zapi.getUtility(IRelationsRegistry)
In real life the indexes needed will be set up manually after object creation In real life the indexes needed will be set up via subscription to
or via subscription to IObjectCreatedEvent - here we have to do this IObjectCreatedEvent - here we have to do this explicitly:
explicitly:
>>> relations.setupIndexes() >>> relations.setupIndexes()
In order to register relations the objects that are referenced have to be In order to register relations the objects that are referenced have to be
registered with an IntIds (unique ids) utility, so we have to set up such registered with an IntIds (unique ids) utility, so we have to set up such
an utility (using a stub/dummy implementation for testing purposes): an utility (using a stub/dummy implementation for testing purposes) and
register the objects with it (in real life this is done automatically
when we add an object to a container):
>>> from cybertools.relation.tests import IntIdsStub >>> from cybertools.relation.tests import IntIdsStub
>>> from zope.app.intid.interfaces import IIntIds >>> from zope.app.intid.interfaces import IIntIds
>>> ztapi.provideUtility(IIntIds, IntIdsStub()) >>> ztapi.provideUtility(IIntIds, IntIdsStub())
>>> intids = zapi.getUtility(IIntIds)
>>> intids.register(clark)
0
>>> intids.register(kirk)
1
>>> intids.register(audrey)
2
>>> intids.register(washington)
3
>>> intids.register(newyork)
4
We also have to provide an adapter for the Relation objects that provides We also have to provide an adapter for the Relation objects that provides
the attributes needed for indexing: the attributes needed for indexing:

View file

@ -27,10 +27,19 @@ $Id$
from persistent import Persistent from persistent import Persistent
from zope.interface import implements from zope.interface import implements
from interfaces import IDyadicRelation, ITriadicRelation from interfaces import IPredicate
from interfaces import IRelation, IDyadicRelation, ITriadicRelation
class Relation(Persistent):
implements(IPredicate, IRelation)
@classmethod
def getPredicateName(cls):
return '%s.%s' % (cls.__module__, cls.__name__)
class DyadicRelation(Persistent): class DyadicRelation(Relation):
implements(IDyadicRelation) implements(IDyadicRelation)
@ -39,7 +48,7 @@ class DyadicRelation(Persistent):
self.second = second self.second = second
class TriadicRelation(Persistent): class TriadicRelation(Relation):
implements(ITriadicRelation) implements(ITriadicRelation)

View file

@ -63,7 +63,7 @@
/> />
<browser:addMenuItem <browser:addMenuItem
title="Relations Registry Utility" title="Relations Registry"
description="A utility that allows the registration of and query for relations" description="A utility that allows the registration of and query for relations"
class=".registry.RelationsRegistry" class=".registry.RelationsRegistry"
permission="zope.ManageSite" permission="zope.ManageSite"

View file

@ -30,7 +30,7 @@ class BrowserTest(FunctionalTestCase):
browser.addHeader('Accept-Language', 'en-US') browser.addHeader('Accept-Language', 'en-US')
browser.open('http://localhost/++etc++site/default/@@contents.html') browser.open('http://localhost/++etc++site/default/@@contents.html')
self.assert_(browser.isHtml) self.assert_(browser.isHtml)
addLink = browser.getLink('Relations Registry Utility') addLink = browser.getLink('Relations Registry')
addLink.click() addLink.click()
self.assert_(browser.isHtml) self.assert_(browser.isHtml)
inp = browser.getControl(name='new_value') inp = browser.getControl(name='new_value')

View file

@ -28,10 +28,26 @@ from zope.app.event.interfaces import IObjectEvent
# relation interfaces # relation interfaces
class IPredicate(Interface):
""" A predicate signifies a relationship. This may be implemented
directly as a relation class, or the relation object may
hold the predicate as an attribute.
"""
def getPredicateName():
""" Return this predicate as a string that may be used for indexing.
"""
class IRelation(Interface): class IRelation(Interface):
""" Base interface for relations. """ Base interface for relations.
""" """
def getPredicateName():
""" Return the predicate of this relation as a string that may be
used for indexing.
"""
class IDyadicRelation(IRelation): class IDyadicRelation(IRelation):
""" Relation connecting two objects. """ Relation connecting two objects.

View file

@ -80,18 +80,20 @@ class RelationsRegistry(Catalog):
self[idx] = FieldIndex(idx, IIndexableRelation) self[idx] = FieldIndex(idx, IIndexableRelation)
def register(self, relation): def register(self, relation):
#self.setupIndexes() if getattr(relation, '__parent__', None) is None:
self.index_doc(_getUid(relation), relation) # Allow the IntIds utility to get a DB connection:
relation.__parent__ = self
self.index_doc(zapi.getUtility(IIntIds).register(relation), relation)
def unregister(self, relation): def unregister(self, relation):
self.unindex_doc(_getUid(relation)) self.unindex_doc(zapi.getUtility(IIntIds).getId(relation))
def query(self, **kw): def query(self, **kw):
for k in kw: for k in kw:
if k == 'relationship': if k == 'relationship':
quString = _getClassString(kw[k]) quString = kw[k].getPredicateName()
else: else:
quString = _getUid(kw[k]) quString = zapi.getUtility(IIntIds).getId(kw[k])
# set min, max # set min, max
kw[k] = (quString, quString) kw[k] = (quString, quString)
return self.searchResults(**kw) return self.searchResults(**kw)
@ -115,29 +117,17 @@ class IndexableRelationAdapter(object):
self.context = context self.context = context
def getRelationship(self): def getRelationship(self):
return _getRelationship(self.context) return self.context.getPredicateName()
relationship = property(getRelationship) relationship = property(getRelationship)
def __getattr__(self, attr): def __getattr__(self, attr):
value = getattr(self.context, attr) value = getattr(self.context, attr)
if isinstance(value, Persistent): if isinstance(value, Persistent):
return _getUid(value) return zapi.getUtility(IIntIds).getId(value)
else: else:
return value return value
# helper functions
def _getUid(ob):
return zapi.getUtility(IIntIds).getId(ob)
def _getRelationship(relation):
return _getClassString(removeSecurityProxy(relation).__class__)
def _getClassString(cls):
return '%s.%s' % (cls.__module__, cls.__name__)
# events and handlers # events and handlers
class RelationInvalidatedEvent(ObjectEvent): class RelationInvalidatedEvent(ObjectEvent):

View file

@ -9,7 +9,8 @@ from zope.app import zapi
from zope.app.intid.interfaces import IIntIds from zope.app.intid.interfaces import IIntIds
from cybertools.relation.interfaces import IDyadicRelation, ITriadicRelation from cybertools.relation.interfaces import IDyadicRelation, ITriadicRelation
from cybertools.relation import DyadicRelation, TriadicRelation from cybertools.relation.interfaces import IRelation, IPredicate
from cybertools.relation import Relation, DyadicRelation, TriadicRelation
from cybertools.relation.interfaces import IRelationsRegistry from cybertools.relation.interfaces import IRelationsRegistry
from cybertools.relation.registry import RelationsRegistry from cybertools.relation.registry import RelationsRegistry
@ -25,6 +26,9 @@ class IntIdsStub:
return self.objs[uid] return self.objs[uid]
def getId(self, ob): def getId(self, ob):
return self.objs.index(ob)
def register(self, ob):
if ob not in self.objs: if ob not in self.objs:
self.objs.append(ob) self.objs.append(ob)
return self.objs.index(ob) return self.objs.index(ob)
@ -38,6 +42,8 @@ class TestRelation(unittest.TestCase):
"Basic tests for the relation package." "Basic tests for the relation package."
def testInterfaces(self): def testInterfaces(self):
verifyClass(IPredicate, Relation)
verifyClass(IRelation, Relation)
self.assert_(IDyadicRelation.providedBy(DyadicRelation(None, None)), self.assert_(IDyadicRelation.providedBy(DyadicRelation(None, None)),
'Interface IDyadicRelation is not implemented by class DyadicRelation.') 'Interface IDyadicRelation is not implemented by class DyadicRelation.')
verifyClass(IDyadicRelation, DyadicRelation) verifyClass(IDyadicRelation, DyadicRelation)