[Checkins] SVN: lovely.relation/trunk/ - extended tests to show
behaviour with multiple relations between the same
Juergen Kartnaller
juergen at kartnaller.at
Fri Oct 19 05:58:36 EDT 2007
Log message for revision 80932:
- extended tests to show behaviour with multiple relations between the same
objects.
- possibility to have multiple relation between the same objects on one
relation property.
- added DataRelationPropertyIn
Changed:
U lovely.relation/trunk/CHANGES.txt
U lovely.relation/trunk/setup.py
U lovely.relation/trunk/src/lovely/relation/README.txt
U lovely.relation/trunk/src/lovely/relation/dataproperty.py
U lovely.relation/trunk/src/lovely/relation/dataproperty.txt
U lovely.relation/trunk/src/lovely/relation/interfaces.py
U lovely.relation/trunk/src/lovely/relation/property.py
U lovely.relation/trunk/src/lovely/relation/property.txt
-=-
Modified: lovely.relation/trunk/CHANGES.txt
===================================================================
--- lovely.relation/trunk/CHANGES.txt 2007-10-18 19:53:21 UTC (rev 80931)
+++ lovely.relation/trunk/CHANGES.txt 2007-10-19 09:58:34 UTC (rev 80932)
@@ -5,6 +5,17 @@
After
=====
+2007/10/17 1.1.2a1
+==================
+
+- extended tests to show behaviour with multiple relations between the same
+ objects.
+
+- possibility to have multiple relation between the same objects on one
+ relation property.
+
+- added DataRelationPropertyIn
+
2007/10/17 1.1.1
================
Modified: lovely.relation/trunk/setup.py
===================================================================
--- lovely.relation/trunk/setup.py 2007-10-18 19:53:21 UTC (rev 80931)
+++ lovely.relation/trunk/setup.py 2007-10-19 09:58:34 UTC (rev 80932)
@@ -21,7 +21,7 @@
from setuptools import setup, find_packages, Extension
setup(name='lovely.relation',
- version='1.1.1',
+ version='1.1.2a1',
url='http://svn.zope.org/lovely.relation',
license='ZPL 2.1',
description='Lovely Relation Packages for Zope3',
Modified: lovely.relation/trunk/src/lovely/relation/README.txt
===================================================================
--- lovely.relation/trunk/src/lovely/relation/README.txt 2007-10-18 19:53:21 UTC (rev 80931)
+++ lovely.relation/trunk/src/lovely/relation/README.txt 2007-10-19 09:58:34 UTC (rev 80932)
@@ -70,7 +70,7 @@
>>> sourceId is None
False
-Let us add an target to the relationship.
+Let us add a target to the relationship.
>>> target = Target('o1 of s1')
>>> relationship.targets = [target]
@@ -150,6 +150,40 @@
[<Source 's1'>, <Source 's2'>]
+Multiple relations beween two objects
+-------------------------------------
+
+We can have the same relation beween two objects more than once.
+
+ >>> rel1 = Relationship(source, [relType], [])
+ >>> rel1.targets = [target]
+ >>> relations.add(rel1)
+
+We have now three relations for our relType.
+
+ >>> list(intids.getObject(s).sources for s in relations.findRelationTokens(relType))
+ [<Source 's1'>, <Source 's2'>, <Source 's1'>]
+
+But we only see distinct sources.
+
+ >>> [s for s in relations.findSources(target, relType)]
+ [<Source 's1'>, <Source 's2'>]
+
+Removing one relation...
+
+ >>> relations.remove(rel1)
+
+changes the seen relations...
+
+ >>> list(intids.getObject(s).sources for s in relations.findRelationTokens(relType))
+ [<Source 's1'>, <Source 's2'>]
+
+but not the sources
+
+ >>> [s for s in relations.findSources(target, relType)]
+ [<Source 's1'>, <Source 's2'>]
+
+
Relation Types
--------------
Modified: lovely.relation/trunk/src/lovely/relation/dataproperty.py
===================================================================
--- lovely.relation/trunk/src/lovely/relation/dataproperty.py 2007-10-18 19:53:21 UTC (rev 80931)
+++ lovely.relation/trunk/src/lovely/relation/dataproperty.py 2007-10-19 09:58:34 UTC (rev 80932)
@@ -24,8 +24,12 @@
from zope.annotation.interfaces import IAttributeAnnotatable
from app import O2OStringTypeRelationship
-from property import RelationPropertyOut
-from interfaces import IDataRelationPropertyOut, IDataRelationship
+from property import RelationPropertyOut, RelationPropertyIn
+from interfaces import (
+ IDataRelationPropertyOut,
+ IDataRelationPropertyIn,
+ IDataRelationship,
+ )
class DataRelationship(O2OStringTypeRelationship):
@@ -106,3 +110,61 @@
except IndexError:
return None
+
+class DataRelationPropertyIn(RelationPropertyIn):
+ interface.implements(IDataRelationPropertyIn)
+
+ def new(self, target):
+ return DataRelationship(source, self)
+
+ def __set__(self, inst, value):
+ if self._field.readonly:
+ raise ValueError(self._name, 'field is readonly')
+ value = removeAllProxies(value)
+ if value is None:
+ v = None
+ elif not self._manager.seqIn:
+ if not IDataRelationship.providedBy(value):
+ raise TypeError
+ if value.target is None:
+ raise ValueError('source for data relation must not be None')
+ v = value
+ v.target = inst
+ if v.relations == []:
+ v.relations = [self._relType]
+ else:
+ v = [removeAllProxies(v) for v in value]
+ for val in v:
+ if not IDataRelationship.providedBy(val):
+ raise TypeError('%s'% val)
+ if val.target is None:
+ raise ValueError('target for data relation must not be None')
+ for val in v:
+ val.target = inst
+ if val.relations == []:
+ val.relations = [self._relType]
+ self._manager.setSourceRelations(inst, v, self._relType)
+ if self._ordered:
+ if v is not None:
+ tokens = list(self._manager.tokenizeValues(v, 'targets'))
+ else:
+ tokens = []
+ inst.__dict__['_o_' + self._name] = tokens
+
+ def __get__(self, inst, klass):
+ if inst is None:
+ return self
+ tokens = self._manager.getTargetRelationTokens(inst, self._relType)
+ if self._ordered:
+ tokens = self._sort(inst, tokens)
+ if not self._uids:
+ tokens = self._manager.resolveValueTokens(tokens, 'sources')
+ tokens = list(tokens)
+ if self._manager.seqIn:
+ return tokens
+ else:
+ try:
+ return tokens[0]
+ except IndexError:
+ return None
+
Modified: lovely.relation/trunk/src/lovely/relation/dataproperty.txt
===================================================================
--- lovely.relation/trunk/src/lovely/relation/dataproperty.txt 2007-10-18 19:53:21 UTC (rev 80931)
+++ lovely.relation/trunk/src/lovely/relation/dataproperty.txt 2007-10-19 09:58:34 UTC (rev 80932)
@@ -63,10 +63,10 @@
... def __repr__(self):
... return '<document %r>' % self.name
- >>> from lovely.relation.property import RelationPropertyIn
+ >>> from lovely.relation.dataproperty import DataRelationPropertyIn
>>> class Chapter(object):
... interface.implements(IChapter)
- ... document = RelationPropertyIn(documentChapter)
+ ... document = DataRelationPropertyIn(documentChapter)
... def __init__(self, content):
... self.content = content
... def __repr__(self):
@@ -168,7 +168,7 @@
>>> img2 = Image(u'Image Two')
-This time we do not use new but instantiate the data relation manually.
+This time we do not use "new" but instantiate the data relation manually.
>>> smallImgRel = DataRelationship(img2)
>>> smallImgRel
@@ -176,11 +176,11 @@
>>> doc1.smallImgRel = smallImgRel
>>> doc1.smallImgRel is smallImgRel
True
- >>> doc1.teaser is rel1
- True
>>> smallImgRel
<DataRelationship None, <image u'Image Two'>, []>
+ >>> doc1.teaser is manualRel
+ True
>>> doc1.teaser = None
>>> doc1.teaser is None
True
@@ -198,7 +198,7 @@
>>> doc1.chapters = (chapterRel1, )
>>> [c.target for c in doc1.chapters]
[<chapter u'Chapter One'>]
- >>> chapter1.document
+ >>> chapter1.document.source
<document u'Doc One'>
>>> chapter2 = Chapter(u'Chapter Two')
@@ -206,9 +206,19 @@
>>> doc1.chapters = doc1.chapters + [chapterRel2]
>>> [c.target for c in doc1.chapters]
[<chapter u'Chapter One'>, <chapter u'Chapter Two'>]
- >>> chapter2.document
+ >>> chapter2.document.source
<document u'Doc One'>
+Here we try to add another relation to chapter2 which must be possible.
+
+ >>> chapterRel3 = Document.chapters.new(chapter2)
+ >>> doc1.chapters = doc1.chapters + [chapterRel3]
+ >>> [c.target for c in doc1.chapters]
+ [<chapter u'Chapter One'>, <chapter u'Chapter Two'>, <chapter u'Chapter Two'>]
+
+ >>> chapter2.document.source
+ <document u'Doc One'>
+
>>> doc1.chapters = None
>>> doc1.chapters
[]
Modified: lovely.relation/trunk/src/lovely/relation/interfaces.py
===================================================================
--- lovely.relation/trunk/src/lovely/relation/interfaces.py 2007-10-18 19:53:21 UTC (rev 80931)
+++ lovely.relation/trunk/src/lovely/relation/interfaces.py 2007-10-19 09:58:34 UTC (rev 80932)
@@ -168,7 +168,7 @@
"""Target being pointed to in the relationship. Readonly.""")
-class IDataRelationPropertyOut(interface.Interface):
+class IDataRelationProperty(interface.Interface):
"""Extends the relation property to be able to annotate the relation"""
def new(self, target):
@@ -179,7 +179,14 @@
annotatable to allow data to be added to a relation.
"""
+class IDataRelationPropertyOut(IDataRelationProperty):
+ """Extends the relation property to be able to annotate the relation"""
+
+class IDataRelationPropertyIn(IDataRelationProperty):
+ """Extends the relation property to be able to annotate the relation"""
+
+
class IRepair(interface.Interface):
"""Repair relations."""
Modified: lovely.relation/trunk/src/lovely/relation/property.py
===================================================================
--- lovely.relation/trunk/src/lovely/relation/property.py 2007-10-18 19:53:21 UTC (rev 80931)
+++ lovely.relation/trunk/src/lovely/relation/property.py 2007-10-19 09:58:34 UTC (rev 80932)
@@ -17,12 +17,18 @@
"""
import interfaces
+
from zope import interface
from zope import component
+
from zope.schema.fieldproperty import FieldProperty
from zope.schema.interfaces import IList, ISequence
+
+from zope.app.intid.interfaces import IIntIds
+
from app import O2OStringTypeRelationship
+
_marker = object()
def _ident(field):
@@ -64,6 +70,10 @@
return component.getUtility(interfaces.IO2OStringTypeRelationships,
name=self.utilName)
+ @property
+ def intids(self):
+ return component.getUtility(IIntIds)
+
def getSourceTokens(self, target, relType):
return self.util.findSourceTokens(target, relType)
@@ -104,8 +114,7 @@
'relations': relType,
'targets': tt})
util.remove(rel.next())
- for addT in list(
- util.relationIndex.resolveValueTokens(addTT, 'targets')):
+ for addT in list(self.resolveValueTokens(addTT, 'targets')):
rel = self._instantiateRelation(source, [relType], addT)
util.add(rel)
@@ -114,26 +123,26 @@
if relations is not None:
if not self.seqOut:
relations = [relations]
- targets = [rel.target for rel in relations]
- newTargetTokens = list(util.relationIndex.tokenizeValues(
- targets, 'targets'))
+ intids = self.intids
+ newRelationTokens = []
+ for rel in relations:
+ # we need this ugly hack to around NotYet exceptions
+ rel = intids.queryId(rel, rel)
+ newRelationTokens.append(intids.queryId(rel, rel))
else:
relations = []
- newTargetTokens = []
- sourceToken = util.relationIndex.tokenizeValues([source],
- 'sources').next()
- oldTargetTokens = util.findTargetTokens(source, relType)
- newTT = set(newTargetTokens)
- oldTT = set(oldTargetTokens)
+ newRelationTokens = []
+ oldRelationTokens = util.findSourceRelationshipTokens(source, relType)
+ newTT = set(newRelationTokens)
+ oldTT = set(oldRelationTokens)
addTT = newTT.difference(oldTT)
delTT = oldTT.difference(newTT)
- for tt in delTT:
- rel = util.relationIndex.findRelationships(
- {'sources': sourceToken,
- 'relations': relType,
- 'targets': tt})
- util.remove(rel.next())
- for token, rel in zip(newTargetTokens, relations):
+ if delTT:
+ intids = self.intids
+ for relId in delTT:
+ rel = intids.getObject(relId)
+ util.remove(rel)
+ for token, rel in zip(newRelationTokens, relations):
if token in addTT:
util.add(rel)
@@ -161,11 +170,38 @@
'sources': st})
self.util.remove(rel.next())
- for addT in list(
- util.relationIndex.resolveValueTokens(addST, 'sources')):
+ for addT in list(self.resolveValueTokens(addST, 'sources')):
rel = self._instantiateRelation(addST, [relType], target)
self.util.add(rel)
+ def setSourceRelations(self, source, relations, relType):
+ util = self.util
+ if relations is not None:
+ if not self.seqOut:
+ relations = [relations]
+ intids = self.intids
+ newRelationTokens = []
+ for rel in relations:
+ # we need this ugly hack to around NotYet exceptions
+ rel = intids.queryId(rel, rel)
+ newRelationTokens.append(rel)
+ else:
+ relations = []
+ newRelationTokens = []
+ oldRelationTokens = util.findTargetRelationshipTokens(target, relType)
+ newTT = set(newRelationTokens)
+ oldTT = set(oldRelationTokens)
+ addTT = newTT.difference(oldTT)
+ delTT = oldTT.difference(newTT)
+ if delTT:
+ intids = self.intids
+ for relId in delTT:
+ rel = intids.getObject(relId)
+ util.remove(rel)
+ for token, rel in zip(newRelationTokens, relations):
+ if token in addTT:
+ util.add(rel)
+
def tokenizeValues(self, values, index):
return self.util.relationIndex.tokenizeValues(values, index)
Modified: lovely.relation/trunk/src/lovely/relation/property.txt
===================================================================
--- lovely.relation/trunk/src/lovely/relation/property.txt 2007-10-18 19:53:21 UTC (rev 80931)
+++ lovely.relation/trunk/src/lovely/relation/property.txt 2007-10-19 09:58:34 UTC (rev 80932)
@@ -240,12 +240,22 @@
Traceback (most recent call last):
...
ValueError: ('backrefs', 'field is readonly')
+
+Backref to doc 3 still exists.
+
>>> n.backrefs[0] is doc3
True
-Backref to doc 3 still exists.
+Setting mutliple relations to the same object can be done...
+ >>> doc3.related = [n, n]
+but only one relation is set
+
+ >>> doc3.related
+ [<note u'note'>]
+
+
Use Of The Relationship Utility
-------------------------------
More information about the Checkins
mailing list