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:
parent
d9b30acb57
commit
ab263bee19
8 changed files with 266 additions and 69 deletions
|
@ -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
101
relation/README.txt
Normal 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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -9,9 +9,6 @@
|
|||
|
||||
<!-- Content declarations -->
|
||||
|
||||
<utility provides=".interfaces.IRelationsRepository"
|
||||
factory=".utilities.RelationsRepository" />
|
||||
|
||||
<utility provides=".interfaces.IRelationsRegistry"
|
||||
factory=".utilities.RelationsRegistry" />
|
||||
|
||||
|
|
|
@ -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
83
relation/registry.py
Normal 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
37
relation/tests.py
Executable 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')
|
|
@ -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 []
|
||||
|
Loading…
Add table
Reference in a new issue