[CMF-checkins] SVN: CMF/branches/yuppie-catalog_setup/CMF - added
setup handlers for catalog tools including sub-objects,
indexes and columns
Yvo Schubbe
y.2005- at wcm-solutions.de
Tue Sep 20 16:50:18 EDT 2005
Log message for revision 38551:
- added setup handlers for catalog tools including sub-objects, indexes and columns
- added utilities to support new kind of setup handlers
(seems to work, but needs more polishing and discussion before merging)
Changed:
A CMF/branches/yuppie-catalog_setup/CMFCalendar/profiles/default/catalog.xml
U CMF/branches/yuppie-catalog_setup/CMFCalendar/setuphandlers.py
A CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/catalog.xml
U CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/export_steps.xml
U CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/import_steps.xml
A CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/
A CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/__init__.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/adapters.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/configure.zcml
A CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/tests/
A CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/tests/__init__.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/tests/test_adapters.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/__init__.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/adapters.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/configure.zcml
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/tests/
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/tests/__init__.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/tests/test_adapters.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/__init__.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/adapters.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/configure.zcml
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/tests/
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/tests/__init__.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/tests/test_adapters.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/catalog.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/configure.zcml
U CMF/branches/yuppie-catalog_setup/CMFSetup/interfaces.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/testing.py
A CMF/branches/yuppie-catalog_setup/CMFSetup/tests/test_catalog.py
U CMF/branches/yuppie-catalog_setup/CMFSetup/utils.py
-=-
Added: CMF/branches/yuppie-catalog_setup/CMFCalendar/profiles/default/catalog.xml
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFCalendar/profiles/default/catalog.xml 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFCalendar/profiles/default/catalog.xml 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<object name="portal_catalog" meta_type="CMF Catalog">
+ <index name="end" meta_type="DateIndex">
+ <property name="index_naive_time_as_local">True</property>
+ </index>
+ <index name="start" meta_type="DateIndex">
+ <property name="index_naive_time_as_local">True</property>
+ </index>
+ <column value="end"/>
+ <column value="start"/>
+</object>
Property changes on: CMF/branches/yuppie-catalog_setup/CMFCalendar/profiles/default/catalog.xml
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: CMF/branches/yuppie-catalog_setup/CMFCalendar/setuphandlers.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFCalendar/setuphandlers.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFCalendar/setuphandlers.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -17,7 +17,6 @@
from Products.CMFCore.utils import getToolByName
-from exceptions import CatalogError
from exceptions import MetadataError
@@ -28,27 +27,8 @@
are implemented for these steps.
"""
site = context.getSite()
- ctool = getToolByName(site, 'portal_catalog')
mdtool = getToolByName(site, 'portal_metadata')
- # Set up a catalog indexes and metadata
- try:
- ctool.addIndex('start', 'DateIndex')
- except CatalogError:
- pass
- try:
- ctool.addIndex('end', 'DateIndex')
- except CatalogError:
- pass
- try:
- ctool.addColumn('start')
- except CatalogError:
- pass
- try:
- ctool.addColumn('end')
- except CatalogError:
- pass
-
# Set up a MetadataTool element policy for events
try:
_ = str # MetadataTool ist not aware of MessageIDs
Added: CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/catalog.xml
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/catalog.xml 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/catalog.xml 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,87 @@
+<?xml version="1.0"?>
+<object name="portal_catalog" meta_type="CMF Catalog">
+ <property name="title"></property>
+ <object name="plaintext_lexicon" meta_type="ZCTextIndex Lexicon">
+ <element name="Whitespace splitter" group="Word Splitter"/>
+ <element name="Case Normalizer" group="Case Normalizer"/>
+ <element name="Remove listed stop words only" group="Stop Words"/>
+ </object>
+ <object name="htmltext_lexicon" meta_type="ZCTextIndex Lexicon">
+ <element name="HTML aware splitter" group="Word Splitter"/>
+ <element name="Case Normalizer" group="Case Normalizer"/>
+ <element name="Remove listed stop words only" group="Stop Words"/>
+ </object>
+ <index name="Date" meta_type="DateIndex">
+ <property name="index_naive_time_as_local">True</property>
+ </index>
+ <index name="Description" meta_type="ZCTextIndex">
+ <indexed_attr value="Description"/>
+ <extra name="index_type" value="Okapi BM25 Rank"/>
+ <extra name="lexicon_id" value="plaintext_lexicon"/>
+ </index>
+ <index name="SearchableText" meta_type="ZCTextIndex">
+ <indexed_attr value="SearchableText"/>
+ <extra name="index_type" value="Okapi BM25 Rank"/>
+ <extra name="lexicon_id" value="htmltext_lexicon"/>
+ </index>
+ <index name="Subject" meta_type="KeywordIndex">
+ <indexed_attr value="Subject"/>
+ </index>
+ <index name="Title" meta_type="ZCTextIndex">
+ <indexed_attr value="Title"/>
+ <extra name="index_type" value="Okapi BM25 Rank"/>
+ <extra name="lexicon_id" value="plaintext_lexicon"/>
+ </index>
+ <index name="Type" meta_type="FieldIndex">
+ <indexed_attr value="Type"/>
+ </index>
+ <index name="allowedRolesAndUsers" meta_type="KeywordIndex">
+ <indexed_attr value="allowedRolesAndUsers"/>
+ </index>
+ <index name="created" meta_type="DateIndex">
+ <property name="index_naive_time_as_local">True</property>
+ </index>
+ <index name="effective" meta_type="DateIndex">
+ <property name="index_naive_time_as_local">True</property>
+ </index>
+ <index name="expires" meta_type="DateIndex">
+ <property name="index_naive_time_as_local">True</property>
+ </index>
+ <index name="getId" meta_type="FieldIndex">
+ <indexed_attr value="getId"/>
+ </index>
+ <index name="in_reply_to" meta_type="FieldIndex">
+ <indexed_attr value="in_reply_to"/>
+ </index>
+ <index name="listCreators" meta_type="KeywordIndex">
+ <indexed_attr value="listCreators"/>
+ </index>
+ <index name="modified" meta_type="DateIndex">
+ <property name="index_naive_time_as_local">True</property>
+ </index>
+ <index name="path" meta_type="PathIndex"/>
+ <index name="portal_type" meta_type="FieldIndex">
+ <indexed_attr value="portal_type"/>
+ </index>
+ <index name="review_state" meta_type="FieldIndex">
+ <indexed_attr value="review_state"/>
+ </index>
+ <column value="CreationDate"/>
+ <column value="Date"/>
+ <column value="Description"/>
+ <column value="EffectiveDate"/>
+ <column value="ExpirationDate"/>
+ <column value="ModificationDate"/>
+ <column value="Subject"/>
+ <column value="Title"/>
+ <column value="Type"/>
+ <column value="created"/>
+ <column value="effective"/>
+ <column value="expires"/>
+ <column value="getIcon"/>
+ <column value="getId"/>
+ <column value="listCreators"/>
+ <column value="modified"/>
+ <column value="portal_type"/>
+ <column value="review_state"/>
+</object>
Property changes on: CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/catalog.xml
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/export_steps.xml
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/export_steps.xml 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/export_steps.xml 2005-09-20 20:50:17 UTC (rev 38551)
@@ -11,6 +11,17 @@
</export-step>
+ <export-step id="catalog"
+ handler="Products.CMFSetup.catalog.exportCatalogTool"
+ title="Catalog Tool">
+
+
+
+ Export catalog tool's sub-objects, indexes and columns.
+
+
+
+ </export-step>
<export-step id="properties"
handler="Products.CMFSetup.properties.exportSiteProperties"
title="Site Properties">
Modified: CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/import_steps.xml
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/import_steps.xml 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFDefault/profiles/default/import_steps.xml 2005-09-20 20:50:17 UTC (rev 38551)
@@ -13,6 +13,19 @@
</import-step>
+ <import-step id="catalog" version="20050918-01"
+ handler="Products.CMFSetup.catalog.importCatalogTool"
+ title="Catalog Tool">
+ <dependency step="toolset"/>
+
+
+
+ Import catalog tool's sub-objects, indexes and columns.
+
+
+
+
+ </import-step>
<import-step id="properties" version="20041215-01"
handler="Products.CMFSetup.properties.importSiteProperties"
title="Site Properties">
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/__init__.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/__init__.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/__init__.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""PluginIndexes support.
+
+$Id$
+"""
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/adapters.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/adapters.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/adapters.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,206 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""PluginIndexes node adapters.
+
+$Id$
+"""
+
+from Products.CMFSetup.interfaces import INodeExporter
+from Products.CMFSetup.interfaces import INodeImporter
+from Products.CMFSetup.interfaces import PURGE
+from Products.CMFSetup.utils import NodeAdapterBase
+from Products.CMFSetup.utils import PropertyManagerHelpers
+
+from Products.PluginIndexes.interfaces import IDateIndex
+from Products.PluginIndexes.interfaces import IDateRangeIndex
+from Products.PluginIndexes.interfaces import IFilteredSet
+from Products.PluginIndexes.interfaces import IPathIndex
+from Products.PluginIndexes.interfaces import IPluggableIndex
+from Products.PluginIndexes.interfaces import ITextIndex
+from Products.PluginIndexes.interfaces import ITopicIndex
+from Products.PluginIndexes.interfaces import IVocabulary
+
+
+class PluggableIndexNodeAdapter(NodeAdapterBase):
+
+ """Node im- and exporter for FieldIndex, KeywordIndex.
+ """
+
+ __used_for__ = IPluggableIndex
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ node = self._getObjectNode('index')
+ for value in self.context.getIndexSourceNames():
+ child = self._doc.createElement('indexed_attr')
+ child.setAttribute('value', value)
+ node.appendChild(child)
+ return node
+
+ def importNode(self, node, mode=PURGE):
+ """Import the object from the DOM node.
+ """
+ indexed_attrs = []
+ for child in node.childNodes:
+ if child.nodeName == 'indexed_attr':
+ indexed_attrs.append(child.getAttribute('value'))
+ self.context.indexed_attrs = indexed_attrs
+ self.context.clear()
+
+
+class DateIndexNodeAdapter(NodeAdapterBase, PropertyManagerHelpers):
+
+ """Node im- and exporter for DateIndex.
+ """
+
+ __used_for__ = IDateIndex
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ node = self._getObjectNode('index')
+ node.appendChild(self._extractProperties())
+ return node
+
+ def importNode(self, node, mode=PURGE):
+ """Import the object from the DOM node.
+ """
+ if mode == PURGE:
+ self._purgeProperties()
+
+ self._initProperties(node, mode)
+ self.context.clear()
+
+
+class DateRangeIndexNodeAdapter(NodeAdapterBase):
+
+ """Node im- and exporter for DateRangeIndex.
+ """
+
+ __used_for__ = IDateRangeIndex
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ node = self._getObjectNode('index')
+ node.setAttribute('since_field', self.context.getSinceField())
+ node.setAttribute('until_field', self.context.getUntilField())
+ return node
+
+ def importNode(self, node, mode=PURGE):
+ """Import the object from the DOM node.
+ """
+ self.context._edit(node.getAttribute('since_field'),
+ node.getAttribute('until_field'))
+ self.context.clear()
+
+
+class PathIndexNodeAdapter(NodeAdapterBase):
+
+ """Node im- and exporter for PathIndex.
+ """
+
+ __used_for__ = IPathIndex
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ return self._getObjectNode('index')
+
+
+class VocabularyNodeAdapter(NodeAdapterBase):
+
+ """Node im- and exporter for Vocabulary.
+ """
+
+ __used_for__ = IVocabulary
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ node = self._getObjectNode('object')
+ node.setAttribute('deprecated', 'True')
+ return node
+
+
+class TextIndexNodeAdapter(NodeAdapterBase):
+
+ """Node im- and exporter for TextIndex.
+ """
+
+ __used_for__ = ITextIndex
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ node = self._getObjectNode('index')
+ node.setAttribute('deprecated', 'True')
+ return node
+
+
+class FilteredSetNodeAdapter(NodeAdapterBase):
+
+ """Node im- and exporter for FilteredSet.
+ """
+
+ __used_for__ = IFilteredSet
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ node = self._getObjectNode('filtered_set')
+ node.setAttribute('expression', self.context.getExpression())
+ return node
+
+ def importNode(self, node, mode=PURGE):
+ """Import the object from the DOM node.
+ """
+ self.context.setExpression(node.getAttribute('expression'))
+ self.context.clear()
+
+
+class TopicIndexNodeAdapter(NodeAdapterBase):
+
+ """Node im- and exporter for TopicIndex.
+ """
+
+ __used_for__ = ITopicIndex
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ node = self._getObjectNode('index')
+ for set in self.context.filteredSets.values():
+ node.appendChild(INodeExporter(set).exportNode(doc))
+ return node
+
+ def importNode(self, node, mode=PURGE):
+ """Import the object from the DOM node.
+ """
+ for child in node.childNodes:
+ if child.nodeName == 'filtered_set':
+ set_id = str(child.getAttribute('name'))
+ set_meta_type = str(child.getAttribute('meta_type'))
+ self.context.addFilteredSet(set_id, set_meta_type, '')
+ set = self.context.filteredSets[set_id]
+ INodeImporter(set).importNode(child)
+ self.context.clear()
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/adapters.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/configure.zcml
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/configure.zcml 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/configure.zcml 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,89 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ >
+
+ <adapter
+ factory=".adapters.PluggableIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeExporter"
+ for="Products.PluginIndexes.interfaces.IPluggableIndex"
+ />
+
+ <adapter
+ factory=".adapters.PluggableIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeImporter"
+ for="Products.PluginIndexes.interfaces.IPluggableIndex"
+ />
+
+ <adapter
+ factory=".adapters.DateIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeExporter"
+ for="Products.PluginIndexes.interfaces.IDateIndex"
+ />
+
+ <adapter
+ factory=".adapters.DateIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeImporter"
+ for="Products.PluginIndexes.interfaces.IDateIndex"
+ />
+
+ <adapter
+ factory=".adapters.DateRangeIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeExporter"
+ for="Products.PluginIndexes.interfaces.IDateRangeIndex"
+ />
+
+ <adapter
+ factory=".adapters.DateRangeIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeImporter"
+ for="Products.PluginIndexes.interfaces.IDateRangeIndex"
+ />
+
+ <adapter
+ factory=".adapters.PathIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeExporter"
+ for="Products.PluginIndexes.interfaces.IPathIndex"
+ />
+
+ <adapter
+ factory=".adapters.PathIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeImporter"
+ for="Products.PluginIndexes.interfaces.IPathIndex"
+ />
+
+ <adapter
+ factory=".adapters.VocabularyNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeExporter"
+ for="Products.PluginIndexes.interfaces.IVocabulary"
+ />
+
+ <adapter
+ factory=".adapters.TextIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeExporter"
+ for="Products.PluginIndexes.interfaces.ITextIndex"
+ />
+
+ <adapter
+ factory=".adapters.FilteredSetNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeExporter"
+ for="Products.PluginIndexes.interfaces.IFilteredSet"
+ />
+
+ <adapter
+ factory=".adapters.FilteredSetNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeImporter"
+ for="Products.PluginIndexes.interfaces.IFilteredSet"
+ />
+
+ <adapter
+ factory=".adapters.TopicIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeExporter"
+ for="Products.PluginIndexes.interfaces.ITopicIndex"
+ />
+
+ <adapter
+ factory=".adapters.TopicIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeImporter"
+ for="Products.PluginIndexes.interfaces.ITopicIndex"
+ />
+
+</configure>
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/tests/__init__.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/tests/__init__.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/tests/__init__.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""PluginIndexes support tests.
+
+$Id$
+"""
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/tests/test_adapters.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/tests/test_adapters.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/tests/test_adapters.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,247 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""PluginIndexes node adapter unit tests.
+
+$Id$
+"""
+
+import unittest
+import Testing
+import Zope2
+Zope2.startup()
+
+from Products.CMFSetup.testing import NodeAdapterTestCase
+
+
+_DATE_XML = """\
+<index name="foo_date" meta_type="DateIndex">
+ <property name="index_naive_time_as_local">True</property>
+</index>
+"""
+
+_DATERANGE_XML = """\
+<index name="foo_daterange" meta_type="DateRangeIndex" since_field="bar" \
+until_field="baz"/>
+"""
+
+_FIELD_XML = """\
+<index name="foo_field" meta_type="FieldIndex">
+ <indexed_attr value="bar"/>
+</index>
+"""
+
+_KEYWORD_XML = """\
+<index name="foo_keyword" meta_type="KeywordIndex">
+ <indexed_attr value="bar"/>
+</index>
+"""
+
+_PATH_XML = """\
+<index name="foo_path" meta_type="PathIndex"/>
+"""
+
+_VOCABULARY_XML = """\
+<object name="foo_vocabulary" meta_type="Vocabulary" deprecated="True"/>
+"""
+
+_TEXT_XML = """\
+<index name="foo_text" meta_type="TextIndex" deprecated="True"/>
+"""
+
+_SET_XML = """\
+<filtered_set name="bar" meta_type="PythonFilteredSet" expression="True"/>
+"""
+
+_TOPIC_XML = """\
+<index name="foo_topic" meta_type="TopicIndex">
+ <filtered_set name="bar" meta_type="PythonFilteredSet" expression="True"/>
+ <filtered_set name="baz" meta_type="PythonFilteredSet" expression="False"/>
+</index>
+"""
+
+
+class DateIndexNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.PluginIndexes.adapters \
+ import DateIndexNodeAdapter
+
+ return DateIndexNodeAdapter
+
+ def setUp(self):
+ from Products.PluginIndexes.DateIndex.DateIndex import DateIndex
+
+ self._obj = DateIndex('foo_date')
+ self._XML = _DATE_XML
+
+
+class DateRangeIndexNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.PluginIndexes.adapters \
+ import DateRangeIndexNodeAdapter
+
+ return DateRangeIndexNodeAdapter
+
+ def _populate(self, obj):
+ obj._edit('bar', 'baz')
+
+ def setUp(self):
+ from Products.PluginIndexes.DateRangeIndex.DateRangeIndex \
+ import DateRangeIndex
+
+ self._obj = DateRangeIndex('foo_daterange')
+ self._XML = _DATERANGE_XML
+
+
+class FieldIndexNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.PluginIndexes.adapters \
+ import PluggableIndexNodeAdapter
+
+ return PluggableIndexNodeAdapter
+
+ def _populate(self, obj):
+ obj.indexed_attrs = ('bar',)
+
+ def setUp(self):
+ from Products.PluginIndexes.FieldIndex.FieldIndex import FieldIndex
+
+ self._obj = FieldIndex('foo_field')
+ self._XML = _FIELD_XML
+
+
+class KeywordIndexNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.PluginIndexes.adapters \
+ import PluggableIndexNodeAdapter
+
+ return PluggableIndexNodeAdapter
+
+ def _populate(self, obj):
+ obj.indexed_attrs = ('bar',)
+
+ def setUp(self):
+ from Products.PluginIndexes.KeywordIndex.KeywordIndex \
+ import KeywordIndex
+
+ self._obj = KeywordIndex('foo_keyword')
+ self._XML = _KEYWORD_XML
+
+
+class PathIndexNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.PluginIndexes.adapters \
+ import PathIndexNodeAdapter
+
+ return PathIndexNodeAdapter
+
+ def setUp(self):
+ from Products.PluginIndexes.PathIndex.PathIndex import PathIndex
+
+ self._obj = PathIndex('foo_path')
+ self._XML = _PATH_XML
+
+
+class VocabularyNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.PluginIndexes.adapters \
+ import VocabularyNodeAdapter
+
+ return VocabularyNodeAdapter
+
+ def setUp(self):
+ from Products.PluginIndexes.TextIndex.Vocabulary import Vocabulary
+
+ self._obj = Vocabulary('foo_vocabulary')
+ self._XML = _VOCABULARY_XML
+
+ def test_importNode(self):
+ pass
+
+
+class TextIndexNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.PluginIndexes.adapters \
+ import TextIndexNodeAdapter
+
+ return TextIndexNodeAdapter
+
+ def setUp(self):
+ from Products.PluginIndexes.TextIndex.TextIndex import TextIndex
+
+ self._obj = TextIndex('foo_text')
+ self._XML = _TEXT_XML
+
+ def test_importNode(self):
+ pass
+
+
+class FilteredSetNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.PluginIndexes.adapters \
+ import FilteredSetNodeAdapter
+
+ return FilteredSetNodeAdapter
+
+ def _populate(self, obj):
+ obj.setExpression('True')
+
+ def setUp(self):
+ from Products.PluginIndexes.TopicIndex.FilteredSet \
+ import PythonFilteredSet
+
+ self._obj = PythonFilteredSet('bar', '')
+ self._XML = _SET_XML
+
+
+class TopicIndexNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.PluginIndexes.adapters \
+ import TopicIndexNodeAdapter
+
+ return TopicIndexNodeAdapter
+
+ def _populate(self, obj):
+ obj.addFilteredSet('bar', 'PythonFilteredSet', 'True')
+ obj.addFilteredSet('baz', 'PythonFilteredSet', 'False')
+
+ def setUp(self):
+ from Products.PluginIndexes.TopicIndex.TopicIndex import TopicIndex
+
+ self._obj = TopicIndex('foo_topic')
+ self._XML = _TOPIC_XML
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(DateIndexNodeAdapterTests),
+ unittest.makeSuite(DateRangeIndexNodeAdapterTests),
+ unittest.makeSuite(FieldIndexNodeAdapterTests),
+ unittest.makeSuite(KeywordIndexNodeAdapterTests),
+ unittest.makeSuite(PathIndexNodeAdapterTests),
+ unittest.makeSuite(VocabularyNodeAdapterTests),
+ unittest.makeSuite(TextIndexNodeAdapterTests),
+ unittest.makeSuite(FilteredSetNodeAdapterTests),
+ unittest.makeSuite(TopicIndexNodeAdapterTests),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/PluginIndexes/tests/test_adapters.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/__init__.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/__init__.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/__init__.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZCTextIndex support.
+
+$Id$
+"""
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/adapters.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/adapters.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/adapters.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,110 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZCTextIndex node adapters.
+
+$Id$
+"""
+
+from BTrees.IOBTree import IOBTree
+from BTrees.Length import Length
+from BTrees.OIBTree import OIBTree
+
+from Products.CMFSetup.interfaces import PURGE
+from Products.CMFSetup.utils import NodeAdapterBase
+
+from Products.ZCTextIndex.interfaces import IZCLexicon
+from Products.ZCTextIndex.interfaces import IZCTextIndex
+from Products.ZCTextIndex.PipelineFactory import element_factory
+
+
+class ZCLexiconNodeAdapter(NodeAdapterBase):
+
+ """Node im- and exporter for ZCTextIndex Lexicon.
+ """
+
+ __used_for__ = IZCLexicon
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ node = self._getObjectNode('object')
+ for element in self.context._pipeline:
+ group, name = self._getKeys(element)
+ child = self._doc.createElement('element')
+ child.setAttribute('group', group)
+ child.setAttribute('name', name)
+ node.appendChild(child)
+ return node
+
+ def importNode(self, node, mode=PURGE):
+ """Import the object from the DOM node.
+ """
+ pipeline = []
+ for child in node.childNodes:
+ if child.nodeName == 'element':
+ element = element_factory.instantiate(
+ child.getAttribute('group'), child.getAttribute('name'))
+ pipeline.append(element)
+ self.context._pipeline = tuple(pipeline)
+ #clear lexicon
+ self.context._wids = OIBTree()
+ self.context._words = IOBTree()
+ self.context.length = Length()
+
+ def _getKeys(self, element):
+ for group in element_factory.getFactoryGroups():
+ for name, factory in element_factory._groups[group].items():
+ if factory == element.__class__:
+ return group, name
+
+
+class ZCTextIndexNodeAdapter(NodeAdapterBase):
+
+ """Node im- and exporter for ZCTextIndex.
+ """
+
+ __used_for__ = IZCTextIndex
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ node = self._getObjectNode('index')
+
+ for value in self.context.getIndexSourceNames():
+ child = self._doc.createElement('indexed_attr')
+ child.setAttribute('value', value)
+ node.appendChild(child)
+
+ child = self._doc.createElement('extra')
+ child.setAttribute('name', 'index_type')
+ child.setAttribute('value', self.context.getIndexType())
+ node.appendChild(child)
+
+ child = self._doc.createElement('extra')
+ child.setAttribute('name', 'lexicon_id')
+ child.setAttribute('value', self.context.lexicon_id)
+ node.appendChild(child)
+
+ return node
+
+ def importNode(self, node, mode=PURGE):
+ """Import the object from the DOM node.
+ """
+ indexed_attrs = []
+ for child in node.childNodes:
+ if child.nodeName == 'indexed_attr':
+ indexed_attrs.append(child.getAttribute('value'))
+ self.context.indexed_attrs = indexed_attrs
+ self.context.clear()
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/adapters.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/configure.zcml
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/configure.zcml 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/configure.zcml 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,29 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ >
+
+ <adapter
+ factory=".adapters.ZCLexiconNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeExporter"
+ for="Products.ZCTextIndex.interfaces.IZCLexicon"
+ />
+
+ <adapter
+ factory=".adapters.ZCLexiconNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeImporter"
+ for="Products.ZCTextIndex.interfaces.IZCLexicon"
+ />
+
+ <adapter
+ factory=".adapters.ZCTextIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeExporter"
+ for="Products.ZCTextIndex.interfaces.IZCTextIndex"
+ />
+
+ <adapter
+ factory=".adapters.ZCTextIndexNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeImporter"
+ for="Products.ZCTextIndex.interfaces.IZCTextIndex"
+ />
+
+</configure>
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/tests/__init__.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/tests/__init__.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/tests/__init__.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZCTextIndex support tests.
+
+$Id$
+"""
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/tests/test_adapters.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/tests/test_adapters.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/tests/test_adapters.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,105 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZCTextIndex node adapter unit tests.
+
+$Id$
+"""
+
+import unittest
+import Testing
+import Zope2
+Zope2.startup()
+
+from Acquisition import Implicit
+
+from Products.CMFSetup.testing import NodeAdapterTestCase
+
+
+class _extra:
+
+ pass
+
+
+class DummyCatalog(Implicit):
+
+ pass
+
+
+_PLEXICON_XML = """\
+<object name="foo_plexicon" meta_type="ZCTextIndex Lexicon">
+ <element name="Whitespace splitter" group="Word Splitter"/>
+ <element name="Case Normalizer" group="Case Normalizer"/>
+ <element name="Remove listed stop words only" group="Stop Words"/>
+</object>
+"""
+
+_ZCTEXT_XML = """\
+<index name="foo_zctext" meta_type="ZCTextIndex">
+ <indexed_attr value="foo_zctext"/>
+ <extra name="index_type" value="Okapi BM25 Rank"/>
+ <extra name="lexicon_id" value="foo_plexicon"/>
+</index>
+"""
+
+
+class ZCLexiconNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.ZCTextIndex.adapters \
+ import ZCLexiconNodeAdapter
+
+ return ZCLexiconNodeAdapter
+
+ def _populate(self, obj):
+ from Products.ZCTextIndex.Lexicon import CaseNormalizer
+ from Products.ZCTextIndex.Lexicon import Splitter
+ from Products.ZCTextIndex.Lexicon import StopWordRemover
+ obj._pipeline = (Splitter(), CaseNormalizer(), StopWordRemover())
+
+ def setUp(self):
+ from Products.ZCTextIndex.ZCTextIndex import PLexicon
+
+ self._obj = PLexicon('foo_plexicon')
+ self._XML = _PLEXICON_XML
+
+
+class ZCTextIndexNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.ZCTextIndex.adapters \
+ import ZCTextIndexNodeAdapter
+
+ return ZCTextIndexNodeAdapter
+
+ def setUp(self):
+ from Products.ZCTextIndex.ZCTextIndex import PLexicon
+ from Products.ZCTextIndex.ZCTextIndex import ZCTextIndex
+
+ catalog = DummyCatalog()
+ catalog.foo_plexicon = PLexicon('foo_plexicon')
+ extra = _extra()
+ extra.lexicon_id = 'foo_plexicon'
+ extra.index_type='Okapi BM25 Rank'
+ self._obj = ZCTextIndex('foo_zctext', extra=extra,
+ caller=catalog).__of__(catalog)
+ self._XML = _ZCTEXT_XML
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(ZCLexiconNodeAdapterTests),
+ unittest.makeSuite(ZCTextIndexNodeAdapterTests),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCTextIndex/tests/test_adapters.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/__init__.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/__init__.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/__init__.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZCatalog support.
+
+$Id$
+"""
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/adapters.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/adapters.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/adapters.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,122 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZCatalog node adapters.
+
+$Id$
+"""
+
+from Products.CMFSetup.interfaces import INodeExporter
+from Products.CMFSetup.interfaces import INodeImporter
+from Products.CMFSetup.interfaces import PURGE
+from Products.CMFSetup.utils import NodeAdapterBase
+from Products.CMFSetup.utils import ObjectManagerHelpers
+from Products.CMFSetup.utils import PropertyManagerHelpers
+
+from Products.ZCatalog.interfaces import IZCatalog
+
+
+class _extra:
+
+ pass
+
+
+class ZCatalogNodeAdapter(NodeAdapterBase, ObjectManagerHelpers,
+ PropertyManagerHelpers):
+
+ """Node im- and exporter for ZCatalog.
+ """
+
+ __used_for__ = IZCatalog
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ node = self._getObjectNode('object')
+ node.appendChild(self._extractProperties())
+ node.appendChild(self._extractObjects())
+ node.appendChild(self._extractIndexes())
+ node.appendChild(self._extractColumns())
+ return node
+
+ def importNode(self, node, mode=PURGE):
+ """Import the object from the DOM node.
+ """
+ if mode == PURGE:
+ self._purgeProperties()
+ self._purgeObjects()
+ self._purgeIndexes()
+ self._purgeColumns()
+
+ self._initProperties(node, mode)
+ self._initObjects(node, mode)
+ self._initIndexes(node, mode)
+ self._initColumns(node, mode)
+
+ def _extractIndexes(self):
+ fragment = self._doc.createDocumentFragment()
+ indexes = self.context.getIndexObjects()[:]
+ indexes.sort(lambda x,y: cmp(x.getId(), y.getId()))
+ for idx in indexes:
+ fragment.appendChild(INodeExporter(idx).exportNode(self._doc))
+ return fragment
+
+ def _purgeIndexes(self):
+ for idx_id in self.context.indexes():
+ self.context.delIndex(idx_id)
+
+ def _initIndexes(self, node, mode):
+ for child in node.childNodes:
+ if child.nodeName != 'index':
+ continue
+ if child.hasAttribute('deprecated'):
+ continue
+ zcatalog = self.context
+
+ idx_id = str(child.getAttribute('name'))
+ if idx_id not in zcatalog.indexes():
+ extra = _extra()
+ for sub in child.childNodes:
+ if sub.nodeName == 'extra':
+ name = str(sub.getAttribute('name'))
+ value = str(sub.getAttribute('value'))
+ setattr(extra, name, value)
+ extra = extra.__dict__ and extra or None
+
+ meta_type = str(child.getAttribute('meta_type'))
+ zcatalog.addIndex(idx_id, meta_type, extra)
+
+ idx = zcatalog._catalog.getIndex(idx_id)
+ INodeImporter(idx).importNode(child, mode)
+
+ def _extractColumns(self):
+ fragment = self._doc.createDocumentFragment()
+ schema = self.context.schema()[:]
+ schema.sort()
+ for col in schema:
+ child = self._doc.createElement('column')
+ child.setAttribute('value', col)
+ fragment.appendChild(child)
+ return fragment
+
+ def _purgeColumns(self):
+ for col in self.context.schema()[:]:
+ self.context.delColumn(col)
+
+ def _initColumns(self, node, mode):
+ for child in node.childNodes:
+ if child.nodeName != 'column':
+ continue
+ col = str(child.getAttribute('value'))
+ if col not in self.context.schema()[:]:
+ self.context.addColumn(col)
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/adapters.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/configure.zcml
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/configure.zcml 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/configure.zcml 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,17 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ >
+
+ <adapter
+ factory=".adapters.ZCatalogNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeExporter"
+ for="Products.ZCatalog.interfaces.IZCatalog"
+ />
+
+ <adapter
+ factory=".adapters.ZCatalogNodeAdapter"
+ provides="Products.CMFSetup.interfaces.INodeImporter"
+ for="Products.ZCatalog.interfaces.IZCatalog"
+ />
+
+</configure>
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/tests/__init__.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/tests/__init__.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/tests/__init__.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZCatalog support tests.
+
+$Id$
+"""
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/tests/test_adapters.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/tests/test_adapters.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/tests/test_adapters.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,148 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZCatalog node adapter unit tests.
+
+$Id$
+"""
+
+import unittest
+import Testing
+import Zope2
+Zope2.startup()
+
+from Products.CMFSetup.interfaces import INodeExporter
+from Products.CMFSetup.testing import NodeAdapterTestCase
+from Products.CMFSetup.utils import PrettyDocument
+
+
+class _extra:
+
+ pass
+
+
+_CATALOG_XML = """\
+<object name="foo_catalog" meta_type="ZCatalog">
+ <property name="title"></property>
+ <object name="foo_plexicon" meta_type="ZCTextIndex Lexicon">
+ <element name="Whitespace splitter" group="Word Splitter"/>
+ <element name="Case Normalizer" group="Case Normalizer"/>
+ <element name="Remove listed stop words only" group="Stop Words"/>
+ </object>
+%s <index name="foo_date" meta_type="DateIndex">
+ <property name="index_naive_time_as_local">True</property>
+ </index>
+ <index name="foo_daterange" meta_type="DateRangeIndex" since_field="bar" \
+until_field="baz"/>
+ <index name="foo_field" meta_type="FieldIndex">
+ <indexed_attr value="bar"/>
+ </index>
+ <index name="foo_keyword" meta_type="KeywordIndex">
+ <indexed_attr value="bar"/>
+ </index>
+ <index name="foo_path" meta_type="PathIndex"/>
+%s <index name="foo_topic" meta_type="TopicIndex">
+ <filtered_set name="bar" meta_type="PythonFilteredSet" expression="True"/>
+ <filtered_set name="baz" meta_type="PythonFilteredSet" expression="False"/>
+ </index>
+ <index name="foo_zctext" meta_type="ZCTextIndex">
+ <indexed_attr value="foo_zctext"/>
+ <extra name="index_type" value="Okapi BM25 Rank"/>
+ <extra name="lexicon_id" value="foo_plexicon"/>
+ </index>
+ <column value="eggs"/>
+ <column value="spam"/>
+</object>
+"""
+
+_TEXT_XML = """\
+ <index name="foo_text" meta_type="TextIndex" deprecated="True"/>
+"""
+
+_VOCABULARY_XML = """\
+ <object name="foo_vocabulary" meta_type="Vocabulary" deprecated="True"/>
+"""
+
+
+class ZCatalogNodeAdapterTests(NodeAdapterTestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFSetup.ZCatalog.adapters import ZCatalogNodeAdapter
+
+ return ZCatalogNodeAdapter
+
+ def _populate(self, obj):
+ from Products.ZCTextIndex.Lexicon import CaseNormalizer
+ from Products.ZCTextIndex.Lexicon import Splitter
+ from Products.ZCTextIndex.Lexicon import StopWordRemover
+ from Products.ZCTextIndex.ZCTextIndex import PLexicon
+
+ obj._setObject('foo_plexicon', PLexicon('foo_plexicon'))
+ lex = obj.foo_plexicon
+ lex._pipeline = (Splitter(), CaseNormalizer(), StopWordRemover())
+
+ obj.addIndex('foo_date', 'DateIndex')
+
+ obj.addIndex('foo_daterange', 'DateRangeIndex')
+ idx = obj._catalog.getIndex('foo_daterange')
+ idx._edit('bar', 'baz')
+
+ obj.addIndex('foo_field', 'FieldIndex')
+ idx = obj._catalog.getIndex('foo_field')
+ idx.indexed_attrs = ('bar',)
+
+ obj.addIndex('foo_keyword', 'KeywordIndex')
+ idx = obj._catalog.getIndex('foo_keyword')
+ idx.indexed_attrs = ('bar',)
+
+ obj.addIndex('foo_path', 'PathIndex')
+
+ obj.addIndex('foo_topic', 'TopicIndex')
+ idx = obj._catalog.getIndex('foo_topic')
+ idx.addFilteredSet('bar', 'PythonFilteredSet', 'True')
+ idx.addFilteredSet('baz', 'PythonFilteredSet', 'False')
+
+ extra = _extra()
+ extra.lexicon_id = 'foo_plexicon'
+ extra.index_type = 'Okapi BM25 Rank'
+ obj.addIndex('foo_zctext', 'ZCTextIndex', extra)
+
+ obj.addColumn('spam')
+ obj.addColumn('eggs')
+
+ def _populate_special(self, obj):
+ from Products.PluginIndexes.TextIndex.Vocabulary import Vocabulary
+
+ self._populate(self._obj)
+ obj._setObject('foo_vocabulary', Vocabulary('foo_vocabulary'))
+ obj.addIndex('foo_text', 'TextIndex')
+
+ def setUp(self):
+ from Products.ZCatalog.ZCatalog import ZCatalog
+
+ self._obj = ZCatalog('foo_catalog')
+ self._XML = _CATALOG_XML % ('', '')
+
+ def test_exportNode_special(self):
+ self._populate_special(self._obj)
+ node = INodeExporter(self._obj).exportNode(PrettyDocument())
+ self.assertEqual(node.toprettyxml(' '),
+ _CATALOG_XML % (_VOCABULARY_XML, _TEXT_XML))
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(ZCatalogNodeAdapterTests),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/ZCatalog/tests/test_adapters.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/catalog.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/catalog.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/catalog.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,64 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Catalog tool setup handlers.
+
+$Id$
+"""
+
+from xml.dom.minidom import parseString
+
+from Products.CMFCore.utils import getToolByName
+
+from interfaces import INodeExporter
+from interfaces import INodeImporter
+from interfaces import PURGE, UPDATE
+from utils import PrettyDocument
+
+_FILENAME = 'catalog.xml'
+
+
+def importCatalogTool(context):
+ """ Import catalog tool.
+ """
+ site = context.getSite()
+ mode = context.shouldPurge() and PURGE or UPDATE
+ ctool = getToolByName(site, 'portal_catalog')
+
+ body = context.readDataFile(_FILENAME)
+ if body is None:
+ return 'Catalog tool: Nothing to import.'
+
+ importer = INodeImporter(ctool, None)
+ if importer is None:
+ return 'Catalog tool: Import adapter misssing.'
+
+ importer.importNode(parseString(body).documentElement, mode=mode)
+ return 'Catalog tool imported.'
+
+def exportCatalogTool(context):
+ """ Export catalog tool.
+ """
+ site = context.getSite()
+
+ ctool = getToolByName(site, 'portal_catalog', None)
+ if ctool is None:
+ return 'Catalog tool: Nothing to export.'
+
+ exporter = INodeExporter(ctool)
+ if exporter is None:
+ return 'Catalog tool: Export adapter misssing.'
+
+ doc = PrettyDocument()
+ doc.appendChild(exporter.exportNode(doc))
+ context.writeDataFile(_FILENAME, doc.toprettyxml(' '), 'text/xml')
+ return 'Catalog tool exported.'
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/catalog.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/configure.zcml
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/configure.zcml 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/configure.zcml 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,11 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ >
+
+ <include package=".PluginIndexes"/>
+
+ <include package=".ZCatalog"/>
+
+ <include package=".ZCTextIndex"/>
+
+</configure>
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: CMF/branches/yuppie-catalog_setup/CMFSetup/interfaces.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/interfaces.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/interfaces.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -506,3 +506,29 @@
o If 'ignore_whitespace', then suppress diffs due only to whitespace
(c.f: 'diff -wbB')
"""
+
+
+from zope.interface import Interface
+
+
+PURGE, UPDATE = range(1, 3)
+
+
+class INodeExporter(Interface):
+
+ """Node exporter.
+ """
+
+ def exportNode(doc):
+ """Export the object as a DOM node.
+ """
+
+
+class INodeImporter(Interface):
+
+ """Node importer.
+ """
+
+ def importNode(node, mode=PURGE):
+ """Import the object from the DOM node.
+ """
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/testing.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/testing.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/testing.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,46 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Node adapter testing utils.
+
+$Id$
+"""
+
+import unittest
+from xml.dom.minidom import parseString
+
+from zope.interface.verify import verifyClass
+
+from interfaces import INodeExporter
+from interfaces import INodeImporter
+from utils import PrettyDocument
+
+
+class NodeAdapterTestCase(unittest.TestCase):
+
+ def _populate(self, obj):
+ pass
+
+ def test_z3interfaces(self):
+ verifyClass(INodeExporter, self._getTargetClass())
+ verifyClass(INodeImporter, self._getTargetClass())
+
+ def test_exportNode(self):
+ self._populate(self._obj)
+ node = INodeExporter(self._obj).exportNode(PrettyDocument())
+ self.assertEqual(node.toprettyxml(' '), self._XML)
+
+ def test_importNode(self):
+ node = parseString(self._XML).documentElement
+ self.assertEqual(INodeImporter(self._obj).importNode(node), None)
+ node = INodeExporter(self._obj).exportNode(PrettyDocument())
+ self.assertEqual(node.toprettyxml(' '), self._XML)
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/testing.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/yuppie-catalog_setup/CMFSetup/tests/test_catalog.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/tests/test_catalog.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/tests/test_catalog.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -0,0 +1,227 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Catalog tool setup handler unit tests.
+
+$Id$
+"""
+
+import unittest
+import Testing
+import Zope2
+Zope2.startup()
+
+from OFS.Folder import Folder
+from Products.ZCTextIndex.Lexicon import CaseNormalizer
+from Products.ZCTextIndex.Lexicon import Splitter
+from Products.ZCTextIndex.Lexicon import StopWordRemover
+from Products.ZCTextIndex.ZCTextIndex import PLexicon
+
+from Products.CMFCore.CatalogTool import CatalogTool
+
+from common import BaseRegistryTests
+from common import DummyExportContext
+from common import DummyImportContext
+
+
+class _extra:
+
+ pass
+
+
+class _CatalogToolSetup(BaseRegistryTests):
+
+ def _initSite(self, foo=2):
+ site = self.root.site = Folder(id='site')
+ ctool = site.portal_catalog = CatalogTool()
+
+ for obj_id in ctool.objectIds():
+ ctool._delObject(obj_id)
+ for idx_id in ctool.indexes():
+ ctool.delIndex(idx_id)
+ for col in ctool.schema()[:]:
+ ctool.delColumn(col)
+
+ if foo > 0:
+ ctool._setObject('foo_plexicon', PLexicon('foo_plexicon'))
+ lex = ctool.foo_plexicon
+ lex._pipeline = (Splitter(), CaseNormalizer(), StopWordRemover())
+
+ extra = _extra()
+ extra.lexicon_id = 'foo_plexicon'
+ extra.index_type = 'Okapi BM25 Rank'
+ ctool.addIndex('foo_zctext', 'ZCTextIndex', extra)
+
+ ctool.addColumn('foo_zctext')
+
+ return site
+
+
+_EMPTY_EXPORT = """\
+<?xml version="1.0"?>
+<object meta_type="CMF Catalog" name="portal_catalog">
+ <property name="title"/>
+</object>
+"""
+
+_NORMAL_EXPORT = """\
+<?xml version="1.0"?>
+<object meta_type="CMF Catalog" name="portal_catalog">
+ <property name="title"/>
+ <object name="foo_plexicon" meta_type="ZCTextIndex Lexicon">
+ <element name="Whitespace splitter" group="Word Splitter"/>
+ <element name="Case Normalizer" group="Case Normalizer"/>
+ <element name="Remove listed stop words only" group="Stop Words"/>
+ </object>
+ <index name="foo_zctext" meta_type="ZCTextIndex">
+ <indexed_attr value="foo_zctext"/>
+ <extra name="index_type" value="Okapi BM25 Rank"/>
+ <extra name="lexicon_id" value="foo_plexicon"/>
+ </index>
+ <column value="foo_zctext"/>
+</object>
+"""
+
+_UPDATE_IMPORT = """\
+<?xml version="1.0"?>
+<object meta_type="CMF Catalog" name="portal_catalog">
+ <index name="foo_date" meta_type="DateIndex">
+ <property name="index_naive_time_as_local">True</property>
+ </index>
+ <column value="foo_date"/>
+</object>
+"""
+
+
+class Test_exportCatalogTool(_CatalogToolSetup):
+
+ def test_unchanged(self):
+ from Products.CMFSetup.catalog import exportCatalogTool
+
+ site = self._initSite(0)
+ context = DummyExportContext(site)
+ exportCatalogTool(context)
+
+ self.assertEqual(len(context._wrote), 1)
+ filename, text, content_type = context._wrote[0]
+ self.assertEqual(filename, 'catalog.xml')
+ self._compareDOM(text, _EMPTY_EXPORT)
+ self.assertEqual(content_type, 'text/xml')
+
+ def test_normal(self):
+ from Products.CMFSetup.catalog import exportCatalogTool
+
+ site = self._initSite(2)
+ context = DummyExportContext(site)
+ exportCatalogTool(context)
+
+ self.assertEqual(len(context._wrote), 1)
+ filename, text, content_type = context._wrote[0]
+ self.assertEqual(filename, 'catalog.xml')
+ self._compareDOM(text, _NORMAL_EXPORT)
+ self.assertEqual(content_type, 'text/xml')
+
+
+class Test_importCatalogTool(_CatalogToolSetup):
+
+ def test_empty_purge(self):
+ from Products.CMFSetup.catalog import importCatalogTool
+
+ site = self._initSite(2)
+ ctool = site.portal_catalog
+
+ self.assertEqual(len(ctool.objectIds()), 1)
+ self.assertEqual(len(ctool.indexes()), 1)
+ self.assertEqual(len(ctool.schema()), 1)
+
+ context = DummyImportContext(site, True)
+ context._files['catalog.xml'] = _EMPTY_EXPORT
+ importCatalogTool(context)
+
+ self.assertEqual(len(ctool.objectIds()), 0)
+ self.assertEqual(len(ctool.indexes()), 0)
+ self.assertEqual(len(ctool.schema()), 0)
+
+ def test_empty_update(self):
+ from Products.CMFSetup.catalog import importCatalogTool
+
+ site = self._initSite(2)
+ ctool = site.portal_catalog
+
+ self.assertEqual(len(ctool.objectIds()), 1)
+ self.assertEqual(len(ctool.indexes()), 1)
+ self.assertEqual(len(ctool.schema()), 1)
+
+ context = DummyImportContext(site, False)
+ context._files['catalog.xml'] = _EMPTY_EXPORT
+ importCatalogTool(context)
+
+ self.assertEqual(len(ctool.objectIds()), 1)
+ self.assertEqual(len(ctool.indexes()), 1)
+ self.assertEqual(len(ctool.schema()), 1)
+
+ def test_normal_purge(self):
+ from Products.CMFSetup.catalog import exportCatalogTool
+ from Products.CMFSetup.catalog import importCatalogTool
+
+ site = self._initSite(2)
+ ctool = site.portal_catalog
+
+ self.assertEqual(len(ctool.objectIds()), 1)
+ self.assertEqual(len(ctool.indexes()), 1)
+ self.assertEqual(len(ctool.schema()), 1)
+
+ context = DummyImportContext(site, True)
+ context._files['catalog.xml'] = _NORMAL_EXPORT
+ importCatalogTool(context)
+
+ self.assertEqual(len(ctool.objectIds()), 1)
+ self.assertEqual(len(ctool.indexes()), 1)
+ self.assertEqual(len(ctool.schema()), 1)
+
+ # complete the roundtrip
+ context = DummyExportContext(site)
+ exportCatalogTool(context)
+
+ self.assertEqual(len(context._wrote), 1)
+ filename, text, content_type = context._wrote[0]
+ self.assertEqual(filename, 'catalog.xml')
+ self._compareDOM(text, _NORMAL_EXPORT)
+ self.assertEqual(content_type, 'text/xml')
+
+ def test_normal_update(self):
+ from Products.CMFSetup.catalog import importCatalogTool
+
+ site = self._initSite(2)
+ ctool = site.portal_catalog
+
+ self.assertEqual(len(ctool.objectIds()), 1)
+ self.assertEqual(len(ctool.indexes()), 1)
+ self.assertEqual(len(ctool.schema()), 1)
+
+ context = DummyImportContext(site, False)
+ context._files['catalog.xml'] = _UPDATE_IMPORT
+ importCatalogTool(context)
+
+ self.assertEqual(len(ctool.objectIds()), 1)
+ self.assertEqual(len(ctool.indexes()), 2)
+ self.assertEqual(len(ctool.schema()), 2)
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(Test_exportCatalogTool),
+ unittest.makeSuite(Test_importCatalogTool),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: CMF/branches/yuppie-catalog_setup/CMFSetup/tests/test_catalog.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: CMF/branches/yuppie-catalog_setup/CMFSetup/utils.py
===================================================================
--- CMF/branches/yuppie-catalog_setup/CMFSetup/utils.py 2005-09-20 20:46:57 UTC (rev 38550)
+++ CMF/branches/yuppie-catalog_setup/CMFSetup/utils.py 2005-09-20 20:50:17 UTC (rev 38551)
@@ -17,6 +17,11 @@
import os
from inspect import getdoc
+from xml.dom.minidom import _nssplit
+from xml.dom.minidom import _write_data
+from xml.dom.minidom import Document
+from xml.dom.minidom import Element
+from xml.dom.minidom import Node
from xml.dom.minidom import parseString as domParseString
from xml.sax.handler import ContentHandler
@@ -27,8 +32,12 @@
from Globals import InitializeClass
from Globals import package_home
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+from zope.interface import implements
from exceptions import BadRequest
+from interfaces import INodeExporter
+from interfaces import INodeImporter
+from interfaces import PURGE
from permissions import ManagePortal
@@ -38,6 +47,7 @@
_xmldir = os.path.join( _pkgdir, 'xml' )
CONVERTER, DEFAULT, KEY = range(3)
+I18NURI = 'http://xml.zope.org/namespaces/i18n'
def _getDottedName( named ):
@@ -512,3 +522,264 @@
return _coalesceTextNodeChildren(d_nodes[0], encoding)
else:
return ''
+
+
+# XXX: Is there any code available in Zope that generates pretty XML? If not,
+# this code has to be improved.
+class _Element(Element):
+
+ """minidom element with 'pretty' XML output.
+ """
+
+ def writexml(self, writer, indent="", addindent="", newl=""):
+ # indent = current indentation
+ # addindent = indentation to add to higher levels
+ # newl = newline string
+ writer.write(indent+"<" + self.tagName)
+
+ attrs = self._get_attributes()
+ a_names = attrs.keys()
+ a_names.sort()
+ if 'title' in a_names:
+ a_names.remove('title')
+ a_names.insert(0, 'title')
+ if 'meta_type' in a_names:
+ a_names.remove('meta_type')
+ a_names.insert(0, 'meta_type')
+ if 'name' in a_names:
+ a_names.remove('name')
+ a_names.insert(0, 'name')
+
+ for a_name in a_names:
+ writer.write(" %s=\"" % a_name)
+ _write_data(writer, attrs[a_name].value)
+ writer.write("\"")
+ if self.childNodes:
+ if self.firstChild.nodeType == Node.TEXT_NODE:
+ writer.write(">")
+ else:
+ writer.write(">%s"%(newl))
+ for node in self.childNodes:
+ if node.nodeType == Node.TEXT_NODE:
+ writer.write(node.data)
+ else:
+ node.writexml(writer,indent+addindent,addindent,newl)
+ if self.lastChild.nodeType == Node.TEXT_NODE:
+ writer.write("</%s>%s" % (self.tagName,newl))
+ else:
+ writer.write("%s</%s>%s" % (indent,self.tagName,newl))
+ else:
+ writer.write("/>%s"%(newl))
+
+
+class PrettyDocument(Document):
+
+ """minidom document with 'pretty' XML output.
+ """
+
+ def createElement(self, tagName):
+ e = _Element(tagName)
+ e.ownerDocument = self
+ return e
+
+ def createElementNS(self, namespaceURI, qualifiedName):
+ prefix, localName = _nssplit(qualifiedName)
+ e = _Element(qualifiedName, namespaceURI, prefix)
+ e.ownerDocument = self
+ return e
+
+ def writexml(self, writer, indent="", addindent="", newl="",
+ encoding = None):
+ if encoding is None:
+ writer.write('<?xml version="1.0"?>\n')
+ else:
+ writer.write('<?xml version="1.0" encoding="%s"?>\n' % encoding)
+ for node in self.childNodes:
+ node.writexml(writer, indent, addindent, newl)
+
+
+class NodeAdapterBase(object):
+
+ """Node im- and exporter base.
+ """
+
+ implements(INodeExporter, INodeImporter)
+
+ def __init__(self, context):
+ self.context = context
+
+ def exportNode(self, doc):
+ """Export the object as a DOM node.
+ """
+ self._doc = doc
+ return self._getObjectNode('object')
+
+ def importNode(self, node, mode=PURGE):
+ """Import the object from the DOM node.
+ """
+
+ def _getObjectNode(self, name):
+ node = self._doc.createElement(name)
+ node.setAttribute('name', self.context.getId())
+ node.setAttribute('meta_type', self.context.meta_type)
+ i18n_domain = getattr(self.context, 'i18n_domain', None)
+ if i18n_domain:
+ node.setAttributeNS(I18NURI, 'i18n:domain', i18n_domain)
+ self._i18n_props = ('title', 'description')
+ return node
+
+ def _getNodeText(self, node):
+ text = ''
+ for child in node.childNodes:
+ if child.nodeName != '#text':
+ continue
+ text += child.nodeValue.lstrip()
+ return text
+
+ def _getNodeTextBoolean(self, node):
+ text = self._getNodeText(node)
+ return text.lower() in ('true', 'yes', '1')
+
+
+class ObjectManagerHelpers(object):
+
+ """ObjectManager im- and export helpers.
+ """
+
+ def _extractObjects(self):
+ fragment = self._doc.createDocumentFragment()
+ for obj in self.context.objectValues():
+ exporter = INodeExporter(obj, None)
+ if exporter is None:
+ continue
+ fragment.appendChild(exporter.exportNode(self._doc))
+ return fragment
+
+ def _purgeObjects(self):
+ for obj_id in self.context.objectIds():
+ self.context._delObject(obj_id)
+
+ def _initObjects(self, node, mode):
+ for child in node.childNodes:
+ if child.nodeName != 'object':
+ continue
+ if child.hasAttribute('deprecated'):
+ continue
+ parent = self.context
+
+ obj_id = str(child.getAttribute('name'))
+ if obj_id not in parent.objectIds():
+ meta_type = str(child.getAttribute('meta_type'))
+ for mt_info in Products.meta_types:
+ if mt_info['name'] == meta_type:
+ parent._setObject(obj_id, mt_info['instance'](obj_id))
+ break
+ else:
+ raise ValueError('unknown meta_type \'%s\'' % obj_id)
+
+ if child.hasAttribute('insert-before'):
+ insert_before = child.getAttribute('insert-before')
+ if insert_before == '*':
+ parent.moveObjectsToTop(obj_id)
+ else:
+ try:
+ position = parent.getObjectPosition(insert_before)
+ parent.moveObjectToPosition(obj_id, position)
+ except ValueError:
+ pass
+ elif child.hasAttribute('insert-after'):
+ insert_after = child.getAttribute('insert-after')
+ if insert_after == '*':
+ parent.moveObjectsToBottom(obj_id)
+ else:
+ try:
+ position = parent.getObjectPosition(insert_after)
+ parent.moveObjectToPosition(obj_id, position+1)
+ except ValueError:
+ pass
+
+ obj = getattr(self.context, obj_id)
+ INodeImporter(obj).importNode(child, mode)
+
+
+class PropertyManagerHelpers(object):
+
+ """PropertyManager im- and export helpers.
+ """
+
+ def _extractProperties(self):
+ fragment = self._doc.createDocumentFragment()
+
+ for prop_map in self.context._propertyMap():
+ if prop_map['id'] == 'i18n_domain':
+ continue
+ node = self._doc.createElement('property')
+
+ prop_id = prop_map['id']
+ node.setAttribute('name', prop_id)
+
+ prop = self.context.getProperty(prop_id)
+ if isinstance(prop, (tuple, list)):
+ for value in prop:
+ child = self._doc.createElement('element')
+ child.setAttribute('value', value)
+ node.appendChild(child)
+ else:
+ if not isinstance(prop, basestring):
+ prop = str(prop)
+ child = self._doc.createTextNode(prop)
+ node.appendChild(child)
+
+ if 'd' in prop_map.get('mode', 'wd') and not prop_id == 'title':
+ type = prop_map.get('type', 'string')
+ node.setAttribute('type', type)
+ select_variable = prop_map.get('select_variable', None)
+ if select_variable is not None:
+ node.setAttribute('select_variable', select_variable)
+
+ if hasattr(self, '_i18n_props') and prop_id in self._i18n_props:
+ node.setAttribute('i18n:translate', '')
+
+ fragment.appendChild(node)
+
+ return fragment
+
+ def _purgeProperties(self):
+ #XXX: not implemented
+ pass
+
+ def _initProperties(self, node, mode):
+ self.context.i18n_domain = node.getAttribute('i18n:domain')
+ for child in node.childNodes:
+ if child.nodeName != 'property':
+ continue
+ obj = self.context
+ prop_id = str(child.getAttribute('name'))
+ prop_map = obj.propdict().get(prop_id, None)
+
+ if prop_map is None:
+ if child.hasAttribute('type'):
+ val = child.getAttribute('select_variable')
+ obj._setProperty(prop_id, val, child.getAttribute('type'))
+ prop_map = obj.propdict().get(prop_id, None)
+ else:
+ raise ValueError('undefined property \'%s\'' % prop_id)
+
+ if not 'w' in prop_map.get('mode', 'wd'):
+ raise BadRequest('%s cannot be changed' % prop_id)
+
+ elements = []
+ for sub in child.childNodes:
+ if sub.nodeName == 'element':
+ elements.append(sub.getAttribute('value'))
+
+ if elements or prop_map.get('type') == 'multiple selection':
+ prop_value = tuple(elements) or ()
+ elif prop_map.get('type') == 'boolean':
+ prop_value = self._getNodeTextBoolean(child)
+ else:
+ # if we pass a *string* to _updateProperty, all other values
+ # are converted to the right type
+ prop_value = self._getNodeText(child)
+
+ obj._updateProperty(prop_id, prop_value)
More information about the CMF-checkins
mailing list