[Zope3-checkins]
SVN: Zope3/branches/jim-indexing/src/zope/app/index/
Removed subscription responsibilities from indexes.
Jim Fulton
jim at zope.com
Tue May 25 08:27:17 EDT 2004
Log message for revision 24957:
Removed subscription responsibilities from indexes.
Indexes are no-longer subscribers.
Also moved the code out of the __init__.py module.
-=-
Modified: Zope3/branches/jim-indexing/src/zope/app/index/browser/field/control.pt
===================================================================
--- Zope3/branches/jim-indexing/src/zope/app/index/browser/field/control.pt 2004-05-25 10:05:18 UTC (rev 24956)
+++ Zope3/branches/jim-indexing/src/zope/app/index/browser/field/control.pt 2004-05-25 12:27:16 UTC (rev 24957)
@@ -20,17 +20,6 @@
information but not update itself further.
</p>
- <!-- XXX: Too much logic for a template -->
- <span tal:condition="request/callSubscribe|nothing" tal:omit-tag="">
- <span tal:define="dummy context/subscribe" tal:omit-tag=""/>
- <span i18n:translate="">Successfully subscribed.</span>
- </span>
-
- <span tal:condition="request/callUnsubscribe|nothing" tal:omit-tag="">
- <span tal:define="dummy context/unsubscribe" tal:omit-tag=""/>
- <span i18n:translate="">Successfully unsubscribed.</span>
- </span>
-
<div tal:condition="context/interface" i18n:translate="">
Adapting objects to:
<span tal:replace="view/interface_name" i18n:name="iface_name" />
@@ -46,21 +35,6 @@
<span tal:replace="context/documentCount" i18n:name="doc_count"/>
</div>
- <form method="POST">
- <span tal:condition="context/isSubscribed" tal:omit-tag="">
- <span i18n:translate="">Subscription state: ON</span>
- <input type="submit" value="Unsubscribe" name="callUnsubscribe"
- i18n:attributes="value unsubscribe-button"/>
- </span>
- <span tal:condition="not:context/isSubscribed" tal:omit-tag="">
- <span i18n:translate="">Subscription state: OFF</span>
- <input type="submit" value="Subscribe" name="callSubscribe"
- i18n:attributes="value subscribe-button"/>
- </span>
- <input type="hidden" name="queryText" value=""
- tal:attributes="value request/queryText|nothing" />
- </form>
-
<form method="GET">
<input type="text" name="queryText" value=""
tal:attributes="value request/queryText|nothing" />
Modified: Zope3/branches/jim-indexing/src/zope/app/index/browser/text/control.pt
===================================================================
--- Zope3/branches/jim-indexing/src/zope/app/index/browser/text/control.pt 2004-05-25 10:05:18 UTC (rev 24956)
+++ Zope3/branches/jim-indexing/src/zope/app/index/browser/text/control.pt 2004-05-25 12:27:16 UTC (rev 24957)
@@ -20,17 +20,6 @@
information but not update itself further.
</p>
- <!-- XXX: Too much logic for a template -->
- <span tal:condition="request/callSubscribe|nothing" tal:omit-tag="">
- <span tal:define="dummy context/subscribe" tal:omit-tag=""/>
- <span i18n:translate="">Successfully subscribed.</span>
- </span>
-
- <span tal:condition="request/callUnsubscribe|nothing" tal:omit-tag="">
- <span tal:define="dummy context/unsubscribe" tal:omit-tag=""/>
- <span i18n:translate="">Successfully unsubscribed.</span>
- </span>
-
<div i18n:translate="">
Documents:
<span tal:replace="context/documentCount" i18n:name="doc_count"/>
@@ -41,21 +30,6 @@
<span tal:replace="context/wordCount" i18n:name="word_count"/>
</div>
- <form method="POST">
- <span tal:condition="context/isSubscribed" tal:omit-tag="">
- <span i18n:translate="">Subscription state: ON</span>
- <input type="submit" value="Unsubscribe" name="callUnsubscribe"
- i18n:attributes="value unsubscribe-button"/>
- </span>
- <span tal:condition="not:context/isSubscribed" tal:omit-tag="">
- <span i18n:translate="">Subscription state: OFF</span>
- <input type="submit" value="Subscribe" name="callSubscribe"
- i18n:attributes="value subscribe-button"/>
- </span>
- <input type="hidden" name="queryText" value=""
- tal:attributes="value request/queryText|nothing" />
- </form>
-
<form method="GET">
<input type="text" name="queryText" value=""
tal:attributes="value request/queryText|nothing" />
Modified: Zope3/branches/jim-indexing/src/zope/app/index/field/index.py
===================================================================
--- Zope3/branches/jim-indexing/src/zope/app/index/field/index.py 2004-05-25 10:05:18 UTC (rev 24956)
+++ Zope3/branches/jim-indexing/src/zope/app/index/field/index.py 2004-05-25 12:27:16 UTC (rev 24957)
@@ -11,13 +11,8 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""This is a field index which can be subscribed to an event service.
+"""This is a field index
-Events related to object creation and deletion are translated into
-index_doc() and unindex_doc() calls.
-
-In addition, this implements TTW subscription management.
-
$Id$
"""
from zope.component import getService
@@ -29,7 +24,7 @@
from zope.app.hub.interfaces import IRegistrationHubEvent
from zope.app.index.interfaces.field import IUIFieldIndex, IUIFieldCatalogIndex
from zope.app.catalog.interfaces.index import ICatalogIndex
-from zope.app.index import InterfaceIndexingSubscriber
+from zope.app.index.ifaceindex import InterfaceIndexingSubscriber
class FieldCatalogIndex(InterfaceIndexingSubscriber, FieldIndexWrapper,
Contained):
@@ -39,36 +34,3 @@
implements(IUIFieldIndex)
- currentlySubscribed = False # Default subscription state
-
- def subscribe(self, channel=None, update=True):
- if self.currentlySubscribed:
- raise RuntimeError, "already subscribed; please unsubscribe first"
- channel = self._getChannel(channel)
- channel.subscribe(self, IRegistrationHubEvent)
- channel.subscribe(self, IObjectModifiedHubEvent)
- if update:
- self._update(channel.iterObjectRegistrations())
- self.currentlySubscribed = True
-
- def unsubscribe(self, channel=None):
- if not self.currentlySubscribed:
- raise RuntimeError, "not subscribed; please subscribe first"
- channel = self._getChannel(channel)
- channel.unsubscribe(self, IObjectModifiedHubEvent)
- channel.unsubscribe(self, IRegistrationHubEvent)
- self.currentlySubscribed = False
-
- def isSubscribed(self):
- return self.currentlySubscribed
-
- def _getChannel(self, channel):
- if channel is None:
- channel = getService(self, HubIds)
- return channel
-
- def _update(self, registrations):
- for location, hubid, wrapped_object in registrations:
- value = self._getValue(wrapped_object)
- if value is not None:
- self.index_doc(hubid, value)
Copied: Zope3/branches/jim-indexing/src/zope/app/index/ifaceindex.py (from rev 24956, Zope3/branches/jim-indexing/src/zope/app/index/__init__.py)
===================================================================
--- Zope3/branches/jim-indexing/src/zope/app/index/__init__.py 2004-05-25 10:05:18 UTC (rev 24956)
+++ Zope3/branches/jim-indexing/src/zope/app/index/ifaceindex.py 2004-05-25 12:27:16 UTC (rev 24957)
@@ -0,0 +1,137 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+$Id$
+"""
+from zope.interface import implements
+from zope.app.index.interfaces import IInterfaceIndexer
+
+class InterfaceIndexingSubscriber(object):
+ """Index interface-defined fields
+
+ Mixin for indexing a particular field name, after first adapting the
+ object to be indexed to an interface.
+
+ The class is meant to be mixed with a base class that defines an
+ index_doc method:
+
+ >>> class BaseIndex(object):
+ ... def __init__(self):
+ ... self.data = []
+ ... def index_doc(self, id, value):
+ ... self.data.append((id, value))
+
+ The class does two things. The first is to get a named field
+ from an object:
+
+ >>> class Data:
+ ... def __init__(self, v):
+ ... self.x = v
+
+ >>> class Index(InterfaceIndexingSubscriber, BaseIndex):
+ ... pass
+
+ >>> index = Index('x')
+ >>> index.index_doc(11, Data(1))
+ >>> index.index_doc(22, Data(2))
+ >>> index.data
+ [(11, 1), (22, 2)]
+
+ A method can be indexed:
+
+ >>> Data.z = lambda self: self.x + 20
+ >>> index = Index('z')
+ >>> index.index_doc(11, Data(1))
+ >>> index.index_doc(22, Data(2))
+ >>> index.data
+ [(11, 21), (22, 22)]
+
+ The class can also adapt an object to an interface:
+
+ >>> from zope.interface import Interface
+ >>> class I(Interface):
+ ... pass
+
+ >>> class Data:
+ ... def __init__(self, v):
+ ... self.x = v
+ ... def __conform__(self, iface):
+ ... if iface is I:
+ ... return Data2(self.x)
+
+ >>> class Data2:
+ ... def __init__(self, v):
+ ... self.y = v*v
+
+ >>> index = Index('y', I)
+ >>> index.index_doc(11, Data(3))
+ >>> index.index_doc(22, Data(2))
+ >>> index.data
+ [(11, 9), (22, 4)]
+
+ When you define an index class, you can define a default
+ interface and/or a default interface:
+
+ >>> class Index(InterfaceIndexingSubscriber, BaseIndex):
+ ... default_interface = I
+ ... default_field_name = 'y'
+
+ >>> index = Index()
+ >>> index.index_doc(11, Data(3))
+ >>> index.index_doc(22, Data(2))
+ >>> index.data
+ [(11, 9), (22, 4)]
+
+ """
+ implements(IInterfaceIndexer)
+ default_field_name = None
+ default_interface = None
+
+ def __init__(self, field_name=None, interface=None):
+ super(InterfaceIndexingSubscriber, self).__init__()
+ if field_name is None and self.default_field_name is None:
+ raise ValueError, "Must pass a field_name"
+ if field_name is None:
+ self._field_name = self.default_field_name
+ else:
+ self._field_name = field_name
+ if interface is None:
+ self._interface = self.default_interface
+ else:
+ self._interface = interface
+
+ field_name = property(lambda self: self._field_name)
+ interface = property(lambda self: self._interface)
+
+ def _getValue(self, object):
+ if self._interface is not None:
+ object = self._interface(object, None)
+ if object is None:
+ return None
+
+ value = getattr(object, self._field_name, None)
+ if value is None:
+ return None
+
+ if callable(value):
+ try:
+ value = value()
+ except:
+ return None
+
+ return value
+
+ def index_doc(self, docid, object):
+ value = self._getValue(object)
+ return super(InterfaceIndexingSubscriber, self).index_doc(docid, value)
Added: Zope3/branches/jim-indexing/src/zope/app/index/tests/test_ifaceindex.py
===================================================================
--- Zope3/branches/jim-indexing/src/zope/app/index/tests/test_ifaceindex.py 2004-05-25 10:05:18 UTC (rev 24956)
+++ Zope3/branches/jim-indexing/src/zope/app/index/tests/test_ifaceindex.py 2004-05-25 12:27:16 UTC (rev 24957)
@@ -0,0 +1,28 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test interface indexers
+
+$Id$
+"""
+import unittest
+from zope.testing.doctestunit import DocTestSuite
+
+def test_suite():
+ return unittest.TestSuite((
+ DocTestSuite('zope.app.index.ifaceindex'),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
+
Property changes on: Zope3/branches/jim-indexing/src/zope/app/index/tests/test_ifaceindex.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: Zope3/branches/jim-indexing/src/zope/app/index/text/index.py
===================================================================
--- Zope3/branches/jim-indexing/src/zope/app/index/text/index.py 2004-05-25 10:05:18 UTC (rev 24956)
+++ Zope3/branches/jim-indexing/src/zope/app/index/text/index.py 2004-05-25 12:27:16 UTC (rev 24957)
@@ -11,11 +11,8 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""This is a text index which can be subscribed to an event service.
+"""This is a text index
-Events related to object creation and deletion are translated into
-index_doc() and unindex_doc() calls.
-
In addition, this implements TTW subscription management.
$Id$
@@ -30,7 +27,7 @@
from zope.app.index.interfaces.text import ISearchableText
from zope.app.index.interfaces.text import IUITextIndex, IUITextCatalogIndex
from zope.interface import implements
-from zope.app.index import InterfaceIndexingSubscriber
+from zope.app.index.ifaceindex import InterfaceIndexingSubscriber
from zope.app.catalog.interfaces.index import ICatalogIndex
@@ -45,37 +42,4 @@
implements(IUITextIndex)
- currentlySubscribed = False # Default subscription state
- def subscribe(wrapped_self, channel=None, update=True):
- if wrapped_self.currentlySubscribed:
- raise RuntimeError, "already subscribed; please unsubscribe first"
- channel = wrapped_self._getChannel(channel)
- channel.subscribe(wrapped_self, IRegistrationHubEvent)
- channel.subscribe(wrapped_self, IObjectModifiedHubEvent)
- if update:
- wrapped_self._update(channel.iterObjectRegistrations())
- wrapped_self.currentlySubscribed = True
-
- def unsubscribe(wrapped_self, channel=None):
- if not wrapped_self.currentlySubscribed:
- raise RuntimeError, "not subscribed; please subscribe first"
- channel = wrapped_self._getChannel(channel)
- channel.unsubscribe(wrapped_self, IObjectModifiedHubEvent)
- channel.unsubscribe(wrapped_self, IRegistrationHubEvent)
- wrapped_self.currentlySubscribed = False
-
- def isSubscribed(self):
- return self.currentlySubscribed
-
- def _getChannel(wrapped_self, channel):
- if channel is None:
- channel = getService(wrapped_self, HubIds)
- return channel
-
- def _update(wrapped_self, registrations):
- for location, hubid, wrapped_object in registrations:
- texts = wrapped_self._getValue(wrapped_object)
- if texts is not None:
- wrapped_self.index_doc(hubid, texts)
-
Deleted: Zope3/branches/jim-indexing/src/zope/app/index/text/tests/test_index.py
===================================================================
--- Zope3/branches/jim-indexing/src/zope/app/index/text/tests/test_index.py 2004-05-25 10:05:18 UTC (rev 24956)
+++ Zope3/branches/jim-indexing/src/zope/app/index/text/tests/test_index.py 2004-05-25 12:27:16 UTC (rev 24957)
@@ -1,144 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Tests for text index.
-
-$Id$
-"""
-
-import unittest
-
-from zope.app.event.objectevent import ObjectModifiedEvent
-from zope.app.site.tests.placefulsetup import PlacefulSetup
-from zope.app.traversing import traverse
-from zope.component import getService
-from zope.app.servicenames import HubIds
-from zope.app.hub.interfaces import \
- IRegistrationHubEvent, IObjectModifiedHubEvent
-from zope.app.hub import \
- ObjectRegisteredHubEvent, ObjectUnregisteredHubEvent, \
- ObjectModifiedHubEvent
-
-from zope.app.index.interfaces.text import ISearchableText
-from zope.app.index.text.index import TextIndex
-from zope.interface import implements
-
-
-class FakeSearchableObject:
- implements(ISearchableText)
- def __init__(self):
- self.texts = [u"Bruce"]
- def getSearchableText(self):
- return self.texts
-
-Bruce = u"Bruce"
-Sheila = u"Sheila"
-
-class Test(PlacefulSetup, unittest.TestCase):
-
- def setUp(self):
- PlacefulSetup.setUp(self, site=True)
- self.index = TextIndex()
- self.rootFolder['myIndex'] = self.index
- self.rootFolder['bruce'] = FakeSearchableObject()
- self.object = self.rootFolder['bruce']
-
- def assertPresent(self, word, docid):
- results, total = self.index.query(word)
- self.assertEqual(total, 1)
- self.assertEqual(results[0][0], docid)
-
- def assertAbsent(self, word):
- self.assertEqual(self.index.query(word), ([], 0))
-
- def testNotification(self):
- docid = 1000
- event = ObjectRegisteredHubEvent(None, docid, object=self.object)
- self.index.notify(event)
- self.assertPresent(Bruce, docid)
-
- self.object.texts = [Sheila]
- event = ObjectModifiedHubEvent(None, docid, object=self.object)
- self.index.notify(event)
- self.assertPresent(Sheila, docid)
- self.assertAbsent(Bruce)
-
- event = ObjectUnregisteredHubEvent(None, docid,
- location="fake",
- object=self.object)
- self.index.notify(event)
- self.assertAbsent(Bruce)
- self.assertAbsent(Sheila)
-
- def testNotIndexing(self):
- docid = 1000
- self.object.texts = None
- event = ObjectRegisteredHubEvent(None, docid, object=self.object)
- self.index.notify(event)
- self.assertEqual(self.index.documentCount(), 0)
-
- def testHubMachinery(self):
- # Technically this is a functional test
- self.createStandardServices()
- index = traverse(self.rootFolder, '/myIndex')
- hub = getService(self.rootFolder, HubIds)
-
- hub.subscribe(index, IRegistrationHubEvent)
- hub.subscribe(index, IObjectModifiedHubEvent)
- location = "/bruce"
-
- hubid = hub.register(location)
- self.assertPresent(Bruce, hubid)
-
- self.object.texts = [Sheila]
- event = ObjectModifiedEvent(self.object)
- hub.notify(event)
- self.assertPresent(Sheila, hubid)
- self.assertAbsent(Bruce)
-
- hub.unregister(location)
- self.assertAbsent(Bruce)
- self.assertAbsent(Sheila)
-
- def testBootstrap(self):
- # Need to set up a HubIds service because the standard subscription
- # mix-ins expect to see one.
- self.createStandardServices()
-
- index = traverse(self.rootFolder, '/myIndex')
- self.assertEqual(index.isSubscribed(), False)
- self.assertAbsent(Bruce)
- self.assertAbsent(Sheila)
- location = '/bruce'
- hub = getService(self.rootFolder, HubIds)
- hubid = hub.register(location)
- index.subscribe(hub)
- self.assertEqual(index.isSubscribed(), True)
- self.assertPresent(Bruce, hubid)
-
- index.unsubscribe(hub)
- self.assertEqual(index.isSubscribed(), False)
- self.assertPresent(Bruce, hubid)
-
- self.object.texts = [Sheila]
- event = ObjectModifiedEvent(self.object)
- hub.notify(event)
- self.assertPresent(Bruce, hubid)
- self.assertAbsent(Sheila)
-
-
-def test_suite():
- return unittest.makeSuite(Test)
-
-if __name__=='__main__':
- unittest.main(defaultTest='test_suite')
More information about the Zope3-Checkins
mailing list