work in progress: cybertools.relation package

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@649 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2005-11-02 08:00:17 +00:00
parent d9b30acb57
commit ab263bee19
8 changed files with 266 additions and 69 deletions

View file

@ -9,7 +9,6 @@ from zope.app import zapi
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(TestMenu),
DocFileSuite('README.txt'),
))

101
relation/README.txt Normal file
View file

@ -0,0 +1,101 @@
Yet Another Relations Engine...
===============================
Let's start with two classes and a few objects that we will connect using
relations:
>>> class Person(object):
... pass
>>> class City(object):
... pass
>>> clark = Person()
>>> kirk = Person()
>>> audrey = Person()
>>> washington = City()
>>> newyork = City()
The relation we'll use tells us in which city a person lives; this is a dyadic
relation as it connects two objects. We also associate the relationship
with an interface as we will later use this interface for querying relations.
Dyadic Relations
~~~~~~~~~~~~~~~~
>>> from cybertools.relation import DyadicRelation
>>> class LivesIn(DyadicRelation):
... pass
We don't directly keep track of relations but use a relations registry for
this. The relations registry is usually a local utility; for testing we use
a simple dummy implementation:
>>> from cybertools.relation.registry import DummyRelationsRegistry
>>> relations = DummyRelationsRegistry()
So we are ready to connect a person and a city using the LivesIn relationship:
>>> relations.register(LivesIn(clark, washington))
>>> relations.register(LivesIn(audrey, newyork))
>>> relations.register(LivesIn(kirk, newyork))
We can now query the relations registry to find out where clark lives and
who lives in New York. For this we use the standard attributes of dyadic
relations, first and second:
>>> clarkRels = relations.query(first=clark)
>>> len(clarkRels)
1
>>> clarkRels[0].second == washington
True
>>> nyRels = relations.query(second=newyork)
>>> len(nyRels)
2
It is also possible to remove a relation from the relation registry:
>>> relations.unregister(
... relations.query(first=audrey, second=newyork)[0]
... )
>>> nyRels = relations.query(second=newyork)
>>> len(nyRels)
1
>>> nyRels[0].first == kirk
True
Triedic Relations
~~~~~~~~~~~~~~~~~
We now extend our setting using a triadic relationship - triadic relations
connect three objects. (If you want to connect more than three objects you
may use combinations of triadic and dyadic relations.)
>>> from cybertools.relation import TriadicRelation
>>> class ParentsOf(TriadicRelation):
... """ first (father) and second (mother) are the parents of
... third (child)."""
>>> relations.register(ParentsOf(clark, audrey, kirk))
When we search for relations that contain clark as first we get both:
>>> clarkRels = relations.query(first=clark)
>>> len(clarkRels)
2
So we want to look only for ParentsOf relationships - this should give us
all relations for clark's children:
>>> clarkChildren = relations.query(relationship=ParentsOf, first=clark)
>>> len(clarkChildren)
1
>>> clarkChildren[0].second == audrey
True
>>> clarkChildren[0].third == kirk
True
Setting up and using a RelationsRegistry local utility
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -1,7 +1,51 @@
# -*- coding: UTF-8 -*-
# -*- Mode: Python; py-indent-offset: 4 -*-
# Copyright (C) 2005 Helmut Merz <helmutm@cy55.de>
#
# Copyright (c) 2005 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
The relation package provides all you need for setting up dyadic and
triadic relations.
$Id$
"""
from persistent import Persistent
from zope.interface import implements
from interfaces import IDyadicRelation, ITriadicRelation
class DyadicRelation(Persistent):
implements(IDyadicRelation)
def __init__(self, first, second):
self.first = first
self.second = second
class TriadicRelation(Persistent):
implements(ITriadicRelation)
def __init__(self, first, second, third):
self.first = first
self.second = second
self.third = third

View file

@ -9,9 +9,6 @@
<!-- Content declarations -->
<utility provides=".interfaces.IRelationsRepository"
factory=".utilities.RelationsRepository" />
<utility provides=".interfaces.IRelationsRegistry"
factory=".utilities.RelationsRegistry" />

View file

@ -25,19 +25,6 @@ $Id$
from zope.interface import Interface, Attribute
class IRelationsRepository(Interface):
""" Local utility for storing relations.
"""
def add(relation):
""" Add the relation given and return the id generated for it.
"""
def remove(relation):
""" Remove the relation given.
"""
class IRelationsRegistry(Interface):
""" Local utility for registering (cataloguing) and searching relations.
"""

83
relation/registry.py Normal file
View file

@ -0,0 +1,83 @@
#
# Copyright (c) 2005 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Implementation of the utilities needed for the relations package.
$Id$
"""
from zope.interface import implements
from zope.app import zapi
from persistent import Persistent
from zope.app.container.contained import Contained
from interfaces import IRelationsRegistry
class DummyRelationsRegistry(object):
""" Dummy implementation for demonstration and test purposes.
"""
implements(IRelationsRegistry)
def __init__(self):
self.relations = []
def register(self, relation):
if relation not in self.relations:
self.relations.append(relation)
def unregister(self, relation):
if relation in self.relations:
self.relations.remove(relation)
def query(self, **kw):
result = []
for r in self.relations:
hit = True
for k in kw:
if k == 'relationship':
if kw[k] != r.__class__:
hit = False
break
elif not hasattr(r, k) or getattr(r, k) != kw[k]:
hit = False
break
if hit:
result.append(r)
return result
class RelationsRegistry(Persistent, Contained):
""" Local utility for registering (cataloguing) and searching relations.
"""
implements(IRelationsRegistry)
def register(self, relation):
pass
def unregister(self, relation):
pass
def query(self, **kw):
result = []
return result

37
relation/tests.py Executable file
View file

@ -0,0 +1,37 @@
# $Id$
import unittest
from zope.testing.doctestunit import DocFileSuite
from zope.app.testing import ztapi
from zope.interface.verify import verifyClass
from zope.app import zapi
from cybertools.relation.interfaces import IDyadicRelation, ITriadicRelation
from cybertools.relation import DyadicRelation, TriadicRelation
from cybertools.relation.interfaces import IRelationsRegistry
from cybertools.relation.registry import RelationsRegistry
class TestRelation(unittest.TestCase):
"Basic tests for the relation package."
def testInterfaces(self):
self.assert_(IDyadicRelation.providedBy(DyadicRelation(None, None)),
'Interface IDyadicRelation is not implemented by class DyadicRelation.')
verifyClass(IDyadicRelation, DyadicRelation)
self.assert_(ITriadicRelation.providedBy(TriadicRelation(None, None, None)),
'Interface ITriadicRelation is not implemented by class TriadicRelation.')
verifyClass(ITriadicRelation, TriadicRelation)
self.assert_(IRelationsRegistry.providedBy(RelationsRegistry()),
'Interface IRelationsRegistry is not implemented by class RelationsRegistry.')
verifyClass(IRelationsRegistry, RelationsRegistry)
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(TestRelation),
DocFileSuite('README.txt'),
))
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')

View file

@ -1,51 +0,0 @@
#
# Copyright (c) 2005 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Implementation of the utilities needed for the relations package.
$Id$
"""
from zope.interface import implements
from zope.app import zapi
class RelationsRepository(Persistent, Contained):
""" Local utility for storing relations.
"""
def add(self, relation):
return 'bla'
def remove(self, relation):
pass
class RelationsRegistry(Persistent, Contained):
""" Local utility for registering (cataloguing) and searching relations.
"""
def register(self, relation):
pass
def unregister(relation):
pass
def query(**kw):
return []