[CMF-checkins] SVN: CMF/trunk/ - moved all GenericSetup related code into 'exportimport' modules

Yvo Schubbe y.2005- at wcm-solutions.de
Mon Oct 17 14:48:25 EDT 2005


Log message for revision 39493:
  - moved all GenericSetup related code into 'exportimport' modules

Changed:
  UU  CMF/trunk/CMFCore/configure.zcml
  A   CMF/trunk/CMFCore/exportimport/
  A   CMF/trunk/CMFCore/exportimport/__init__.py
  A   CMF/trunk/CMFCore/exportimport/actions.py
  A   CMF/trunk/CMFCore/exportimport/configure.zcml
  A   CMF/trunk/CMFCore/exportimport/content.py
  A   CMF/trunk/CMFCore/exportimport/cookieauth.py
  A   CMF/trunk/CMFCore/exportimport/tests/
  A   CMF/trunk/CMFCore/exportimport/tests/__init__.py
  A   CMF/trunk/CMFCore/exportimport/tests/conformance.py
  A   CMF/trunk/CMFCore/exportimport/tests/test_actions.py
  A   CMF/trunk/CMFCore/exportimport/tests/test_content.py
  A   CMF/trunk/CMFCore/exportimport/tests/test_cookieauth.py
  D   CMF/trunk/CMFCore/exportimport.py
  D   CMF/trunk/CMFCore/exportimport.zcml
  D   CMF/trunk/CMFCore/nodeadapters.py
  D   CMF/trunk/CMFCore/tests/conformance.py
  D   CMF/trunk/CMFCore/tests/test_exportimport.py
  D   CMF/trunk/CMFCore/tests/test_nodeadapters.py
  _U  CMF/trunk/CMFDefault/exportimport.zcml
  D   CMF/trunk/GenericSetup/MailHost/adapters.py
  U   CMF/trunk/GenericSetup/MailHost/configure.zcml
  A   CMF/trunk/GenericSetup/MailHost/exportimport.py
  D   CMF/trunk/GenericSetup/MailHost/tests/test_adapters.py
  A   CMF/trunk/GenericSetup/MailHost/tests/test_exportimport.py
  D   CMF/trunk/GenericSetup/PluginIndexes/adapters.py
  U   CMF/trunk/GenericSetup/PluginIndexes/configure.zcml
  A   CMF/trunk/GenericSetup/PluginIndexes/exportimport.py
  D   CMF/trunk/GenericSetup/PluginIndexes/tests/test_adapters.py
  A   CMF/trunk/GenericSetup/PluginIndexes/tests/test_exportimport.py
  D   CMF/trunk/GenericSetup/ZCTextIndex/adapters.py
  U   CMF/trunk/GenericSetup/ZCTextIndex/configure.zcml
  A   CMF/trunk/GenericSetup/ZCTextIndex/exportimport.py
  D   CMF/trunk/GenericSetup/ZCTextIndex/tests/test_adapters.py
  A   CMF/trunk/GenericSetup/ZCTextIndex/tests/test_exportimport.py
  D   CMF/trunk/GenericSetup/ZCatalog/adapters.py
  U   CMF/trunk/GenericSetup/ZCatalog/configure.zcml
  A   CMF/trunk/GenericSetup/ZCatalog/exportimport.py
  D   CMF/trunk/GenericSetup/ZCatalog/tests/test_adapters.py
  A   CMF/trunk/GenericSetup/ZCatalog/tests/test_exportimport.py

-=-
Modified: CMF/trunk/CMFCore/configure.zcml
===================================================================
--- CMF/trunk/CMFCore/configure.zcml	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/CMFCore/configure.zcml	2005-10-17 18:48:24 UTC (rev 39493)
@@ -2,59 +2,11 @@
     xmlns="http://namespaces.zope.org/zope">
 
   <include
-    package=".browser"
-    />
+      package=".browser"
+      />
 
   <include
-    file="exportimport.zcml"
-    />
-
-  <adapter
-      factory=".nodeadapters.ActionCategoryNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for=".interfaces.IActionCategory"
+      package=".exportimport"
       />
 
-  <adapter
-      factory=".nodeadapters.ActionCategoryNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for=".interfaces.IActionCategory"
-      />
-
-  <adapter
-      factory=".nodeadapters.ActionNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for=".interfaces.IAction"
-      />
-
-  <adapter
-      factory=".nodeadapters.ActionNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for=".interfaces.IAction"
-      />
-
-  <adapter
-      factory=".nodeadapters.ActionsToolNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for=".interfaces.IActionsTool"
-      />
-
-  <adapter
-      factory=".nodeadapters.ActionsToolNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for=".interfaces.IActionsTool"
-      />
-
-  <adapter
-      factory=".nodeadapters.CookieCrumblerNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for=".interfaces.ICookieCrumbler"
-      />
-
-  <adapter
-      factory=".nodeadapters.CookieCrumblerNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for=".interfaces.ICookieCrumbler"
-      />
-
 </configure>


Property changes on: CMF/trunk/CMFCore/configure.zcml
___________________________________________________________________
Name: svn:keywords
   - Id

Added: CMF/trunk/CMFCore/exportimport/__init__.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/__init__.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/CMFCore/exportimport/__init__.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,19 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""CMFCore export / import support.
+
+$Id$
+"""
+
+from content import exportSiteStructure
+from content import importSiteStructure


Property changes on: CMF/trunk/CMFCore/exportimport/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Copied: CMF/trunk/CMFCore/exportimport/actions.py (from rev 39486, CMF/trunk/CMFCore/nodeadapters.py)
===================================================================
--- CMF/trunk/CMFCore/nodeadapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/CMFCore/exportimport/actions.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,219 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Actions tool node adapters.
+
+$Id$
+"""
+
+from Products.GenericSetup.interfaces import PURGE, UPDATE
+from Products.GenericSetup.utils import I18NURI
+from Products.GenericSetup.utils import NodeAdapterBase
+from Products.GenericSetup.utils import ObjectManagerHelpers
+from Products.GenericSetup.utils import PropertyManagerHelpers
+
+from Products.CMFCore.interfaces import IAction
+from Products.CMFCore.interfaces import IActionCategory
+from Products.CMFCore.interfaces import IActionsTool
+from Products.CMFCore.interfaces.portal_actions \
+        import ActionProvider as IActionProvider
+from Products.CMFCore.utils import getToolByName
+
+_SPECIAL_PROVIDERS = ('portal_actions', 'portal_types', 'portal_workflow')
+
+
+class ActionCategoryNodeAdapter(NodeAdapterBase, ObjectManagerHelpers,
+                                PropertyManagerHelpers):
+
+    """Node im- and exporter for ActionCategory.
+    """
+
+    __used_for__ = IActionCategory
+
+    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())
+        return node
+
+    def importNode(self, node, mode=PURGE):
+        """Import the object from the DOM node.
+        """
+        if mode == PURGE:
+            self._purgeProperties()
+            self._purgeObjects()
+
+        self._initProperties(node, mode)
+        self._initObjects(node, mode)
+
+
+class ActionNodeAdapter(NodeAdapterBase, PropertyManagerHelpers):
+
+    """Node im- and exporter for Action.
+    """
+
+    __used_for__ = IAction
+
+    def exportNode(self, doc):
+        """Export the object as a DOM node.
+        """
+        self._doc = doc
+        node = self._getObjectNode('object')
+        node.appendChild(self._extractProperties())
+        return node
+
+    def importNode(self, node, mode=PURGE):
+        """Import the object from the DOM node.
+        """
+        self._initProperties(node, mode)
+
+
+class ActionsToolNodeAdapter(NodeAdapterBase, ObjectManagerHelpers):
+
+    """Node im- and exporter for ActionsTool.
+    """
+
+    __used_for__ = IActionsTool
+
+    def exportNode(self, doc):
+        """Export the object as a DOM node.
+        """
+        self._doc = doc
+        node = self._getObjectNode('object')
+        node.setAttribute('xmlns:i18n', I18NURI)
+        node.appendChild(self._extractProviders())
+        node.appendChild(self._extractObjects())
+        return node
+
+    def importNode(self, node, mode=PURGE):
+        """Import the object from the DOM node.
+        """
+        if mode == PURGE:
+            self._purgeProviders()
+            self._purgeObjects()
+
+        self._initObjects(node, mode)
+        self._initProviders(node, mode)
+
+    def _extractProviders(self):
+        fragment = self._doc.createDocumentFragment()
+        for provider_id in self.context.listActionProviders():
+            child = self._doc.createElement('action-provider')
+            child.setAttribute('name', provider_id)
+            # BBB: for CMF 1.5 profiles
+            sub = self._extractOldstyleActions(provider_id)
+            child.appendChild(sub)
+            fragment.appendChild(child)
+        return fragment
+
+    def _extractOldstyleActions(self, provider_id):
+        # BBB: for CMF 1.5 profiles
+        fragment = self._doc.createDocumentFragment()
+
+        provider = getToolByName(self.context, provider_id)
+        if not IActionProvider.isImplementedBy(provider):
+            return fragment
+
+        if provider_id == 'portal_actions':
+            actions = provider._actions
+        else:
+            actions = provider.listActions()
+
+        if actions and isinstance(actions[0], dict):
+            return fragment
+
+        for ai in actions:
+            mapping = ai.getMapping()
+            child = self._doc.createElement('action')
+            child.setAttribute('action_id', mapping['id'])
+            child.setAttribute('category', mapping['category'])
+            child.setAttribute('condition_expr', mapping['condition'])
+            child.setAttribute('title', mapping['title'])
+            child.setAttribute('url_expr', mapping['action'])
+            child.setAttribute('visible', str(mapping['visible']))
+            for permission in mapping['permissions']:
+                sub = self._doc.createElement('permission')
+                sub.appendChild(self._doc.createTextNode(permission))
+                child.appendChild(sub)
+            fragment.appendChild(child)
+        return fragment
+
+    def _purgeProviders(self):
+        for provider_id in self.context.listActionProviders():
+            self.context.deleteActionProvider(provider_id)
+
+    def _initProviders(self, node, mode):
+        for child in node.childNodes:
+            if child.nodeName != 'action-provider':
+                continue
+
+            provider_id = str(child.getAttribute('name'))
+            if not provider_id:
+                # BBB: for CMF 1.5 profiles
+                provider_id = str(child.getAttribute('id'))
+            if child.hasAttribute('remove'):
+                if provider_id in self.context.listActionProviders():
+                    self.context.deleteActionProvider(provider_id)
+                continue
+
+            if provider_id in _SPECIAL_PROVIDERS and \
+                    provider_id not in self.context.listActionProviders():
+                self.context.addActionProvider(provider_id)
+
+            # BBB: for CMF 1.5 profiles
+            self._initOldstyleActions(child, mode)
+
+    def _initOldstyleActions(self, node, mode):
+        # BBB: for CMF 1.5 profiles
+        doc = node.ownerDocument
+        fragment = doc.createDocumentFragment()
+        for child in node.childNodes:
+            if child.nodeName != 'action':
+                continue
+
+            parent = fragment
+            for category_id in child.getAttribute('category').split('/'):
+                newnode = doc.createElement('object')
+                newnode.setAttribute('name', str(category_id))
+                newnode.setAttribute('meta_type', 'CMF Action Category')
+                parent.appendChild(newnode)
+                parent = newnode
+            newnode = doc.createElement('object')
+            newnode.setAttribute('name', str(child.getAttribute('action_id')))
+            newnode.setAttribute('meta_type', 'CMF Action')
+
+            mapping = {'title': 'title',
+                       'url_expr': 'url_expr',
+                       'condition_expr': 'available_expr',
+                       'visible': 'visible'}
+            for old, new in mapping.iteritems():
+                newchild = doc.createElement('property')
+                newchild.setAttribute('name', new)
+                newsub = doc.createTextNode(child.getAttribute(old))
+                newchild.appendChild(newsub)
+                newnode.appendChild(newchild)
+
+            newchild = doc.createElement('property')
+            newchild.setAttribute('name', 'permissions')
+            for sub in child.childNodes:
+                if sub.nodeName == 'permission':
+                    newsub = doc.createElement('element')
+                    newsub.setAttribute('value', self._getNodeText(sub))
+                    newchild.appendChild(newsub)
+            newnode.appendChild(newchild)
+
+            parent.appendChild(newnode)
+
+        self._initObjects(fragment, UPDATE)

Copied: CMF/trunk/CMFCore/exportimport/configure.zcml (from rev 39486, CMF/trunk/CMFCore/exportimport.zcml)
===================================================================
--- CMF/trunk/CMFCore/exportimport.zcml	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/CMFCore/exportimport/configure.zcml	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,103 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    i18n_domain="cmf"
+    >
+
+  <adapter
+      factory=".actions.ActionCategoryNodeAdapter"
+      provides="Products.GenericSetup.interfaces.INodeExporter"
+      for="Products.CMFCore.interfaces.IActionCategory"
+      />
+
+  <adapter
+      factory=".actions.ActionCategoryNodeAdapter"
+      provides="Products.GenericSetup.interfaces.INodeImporter"
+      for="Products.CMFCore.interfaces.IActionCategory"
+      />
+
+  <adapter
+      factory=".actions.ActionNodeAdapter"
+      provides="Products.GenericSetup.interfaces.INodeExporter"
+      for="Products.CMFCore.interfaces.IAction"
+      />
+
+  <adapter
+      factory=".actions.ActionNodeAdapter"
+      provides="Products.GenericSetup.interfaces.INodeImporter"
+      for="Products.CMFCore.interfaces.IAction"
+      />
+
+  <adapter
+      factory=".actions.ActionsToolNodeAdapter"
+      provides="Products.GenericSetup.interfaces.INodeExporter"
+      for="Products.CMFCore.interfaces.IActionsTool"
+      />
+
+  <adapter
+      factory=".actions.ActionsToolNodeAdapter"
+      provides="Products.GenericSetup.interfaces.INodeImporter"
+      for="Products.CMFCore.interfaces.IActionsTool"
+      />
+
+  <adapter
+      factory=".content.StructureFolderWalkingAdapter"
+      provides="Products.CMFCore.interfaces.IFilesystemExporter"
+      for="Products.CMFCore.interfaces.IFolderish"
+      />
+
+  <adapter
+      factory=".content.StructureFolderWalkingAdapter"
+      provides="Products.CMFCore.interfaces.IFilesystemImporter"
+      for="Products.CMFCore.interfaces.IFolderish"
+      />
+
+  <adapter
+      factory=".content.CSVAwareFileAdapter"
+      provides="Products.CMFCore.interfaces.IFilesystemExporter"
+      for="Products.CMFCore.interfaces.ICSVAware"
+      />
+
+  <adapter
+      factory=".content.CSVAwareFileAdapter"
+      provides="Products.CMFCore.interfaces.IFilesystemImporter"
+      for="Products.CMFCore.interfaces.ICSVAware"
+      />
+
+  <adapter
+      factory=".content.INIAwareFileAdapter"
+      provides="Products.CMFCore.interfaces.IFilesystemExporter"
+      for="Products.CMFCore.interfaces.IINIAware"
+      />
+
+  <adapter
+      factory=".content.INIAwareFileAdapter"
+      provides="Products.CMFCore.interfaces.IFilesystemImporter"
+      for="Products.CMFCore.interfaces.IINIAware"
+      />
+
+  <adapter
+      factory=".content.DAVAwareFileAdapter"
+      provides="Products.CMFCore.interfaces.IFilesystemExporter"
+      for="Products.CMFCore.interfaces.IDAVAware"
+      />
+
+  <adapter
+      factory=".content.DAVAwareFileAdapter"
+      provides="Products.CMFCore.interfaces.IFilesystemImporter"
+      for="Products.CMFCore.interfaces.IDAVAware"
+      />
+
+  <adapter
+      factory=".cookieauth.CookieCrumblerNodeAdapter"
+      provides="Products.GenericSetup.interfaces.INodeExporter"
+      for="Products.CMFCore.interfaces.ICookieCrumbler"
+      />
+
+  <adapter
+      factory=".cookieauth.CookieCrumblerNodeAdapter"
+      provides="Products.GenericSetup.interfaces.INodeImporter"
+      for="Products.CMFCore.interfaces.ICookieCrumbler"
+      />
+
+</configure>


Property changes on: CMF/trunk/CMFCore/exportimport/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Copied: CMF/trunk/CMFCore/exportimport/content.py (from rev 39486, CMF/trunk/CMFCore/exportimport.py)
===================================================================
--- CMF/trunk/CMFCore/exportimport.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/CMFCore/exportimport/content.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,324 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Filesystem exporter / importer adapters.
+
+$Id$
+"""
+
+from csv import reader
+from csv import register_dialect
+from csv import writer
+from ConfigParser import ConfigParser
+import re
+from StringIO import StringIO
+
+from zope.interface import implements
+from zope.interface import directlyProvides
+
+from Products.CMFCore.interfaces import IFilesystemExporter
+from Products.CMFCore.interfaces import IFilesystemImporter
+from Products.CMFCore.interfaces import ISiteRoot
+from Products.CMFCore.utils import getToolByName
+
+#
+#   setup_tool handlers
+#
+def exportSiteStructure(context):
+    IFilesystemExporter(context.getSite()).export(context, 'structure')
+
+def importSiteStructure(context):
+    IFilesystemImporter(context.getSite()).import_(context, 'structure')
+
+
+#
+#   Filesystem export/import adapters
+#
+class StructureFolderWalkingAdapter(object):
+    """ Tree-walking exporter for "folderish" types.
+
+    Folderish instances are mapped to directories within the 'structure'
+    portion of the profile, where the folder's relative path within the site
+    corresponds to the path of its directory under 'structure'.
+
+    The subobjects of a folderish instance are enumerated in the '.objects'
+    file in the corresponding directory.  This file is a CSV file, with one
+    row per subobject, with the following wtructure::
+
+     "<subobject id>","<subobject portal_type>"
+
+    Subobjects themselves are represented as individual files or
+    subdirectories within the parent's directory.
+    """
+
+    implements(IFilesystemExporter, IFilesystemImporter)
+
+    def __init__(self, context):
+        self.context = context
+
+    def export(self, export_context, subdir):
+        """ See IFilesystemExporter.
+        """
+        # Enumerate exportable children
+        exportable = self.context.contentItems()
+        exportable = [x + (IFilesystemExporter(x, None),) for x in exportable]
+        exportable = [x for x in exportable if x[1] is not None]
+
+        stream = StringIO()
+        csv_writer = writer(stream)
+
+        for object_id, object, ignored in exportable:
+            csv_writer.writerow((object_id, object.getPortalTypeName()))
+
+        if not ISiteRoot.providedBy(self.context):
+            subdir = '%s/%s' % (subdir, self.context.getId())
+
+        export_context.writeDataFile('.objects',
+                                     text=stream.getvalue(),
+                                     content_type='text/comma-separated-values',
+                                     subdir=subdir,
+                                    )
+
+        parser = ConfigParser()
+
+        parser.set('DEFAULT', 'Title', self.context.Title())
+        parser.set('DEFAULT', 'Description', self.context.Description())
+        stream = StringIO()
+        parser.write(stream)
+
+        export_context.writeDataFile('.properties',
+                                    text=stream.getvalue(),
+                                    content_type='text/plain',
+                                    subdir=subdir,
+                                    )
+
+        for id, object in self.context.objectItems():
+
+            adapter = IFilesystemExporter(object, None)
+
+            if adapter is not None:
+                adapter.export(export_context, subdir)
+
+    def import_(self, import_context, subdir):
+        """ See IFilesystemImporter.
+        """
+        context = self.context
+        if not ISiteRoot.providedBy(context):
+            subdir = '%s/%s' % (subdir, context.getId())
+
+        preserve = import_context.readDataFile('.preserve', subdir)
+
+        prior = context.contentIds()
+
+        if not preserve:
+            preserve = []
+        else:
+            preserve = _globtest(preserve, prior)
+
+        for id in prior:
+            if id not in preserve:
+                context._delObject(id)
+
+        objects = import_context.readDataFile('.objects', subdir)
+        if objects is None:
+            return
+
+        dialect = 'excel'
+        stream = StringIO(objects)
+
+        rowiter = reader(stream, dialect)
+
+        existing = context.objectIds()
+
+        for object_id, portal_type in rowiter:
+
+            if object_id not in existing:
+                object = self._makeInstance(object_id, portal_type,
+                                            subdir, import_context)
+                if object is None:
+                    message = "Couldn't make instance: %s/%s" % (subdir,
+                                                                 object_id)
+                    import_context.note('SFWA', message)
+                    continue
+
+            wrapped = context._getOb(object_id)
+
+            IFilesystemImporter(wrapped).import_(import_context, subdir)
+
+    def _makeInstance(self, id, portal_type, subdir, import_context):
+
+        context = self.context
+        properties = import_context.readDataFile('.properties',
+                                                 '%s/%s' % (subdir, id))
+        tool = getToolByName(context, 'portal_types')
+
+        try:
+            tool.constructContent(portal_type, context, id)
+        except ValueError: # invalid type
+            return None
+
+        content = context._getOb(id)
+
+        if properties is not None:
+            lines = properties.splitlines()
+
+            stream = StringIO('\n'.join(lines))
+            parser = ConfigParser(defaults={'title': '', 'description': 'NONE'})
+            parser.readfp(stream)
+
+            title = parser.get('DEFAULT', 'title')
+            description = parser.get('DEFAULT', 'description')
+
+            content.setTitle(title)
+            content.setDescription(description)
+
+        return content
+
+
+def _globtest(globpattern, namelist):
+    """ Filter names in 'namelist', returning those which match 'globpattern'.
+    """
+    import re
+    pattern = globpattern.replace(".", r"\.")       # mask dots
+    pattern = pattern.replace("*", r".*")           # change glob sequence
+    pattern = pattern.replace("?", r".")            # change glob char
+    pattern = '|'.join(pattern.split())             # 'or' each line
+
+    compiled = re.compile(pattern)
+
+    return filter(compiled.match, namelist)
+
+
+class CSVAwareFileAdapter(object):
+    """ Adapter for content whose "natural" representation is CSV.
+    """
+    implements(IFilesystemExporter, IFilesystemImporter)
+
+    def __init__(self, context):
+        self.context = context
+
+    def export(self, export_context, subdir):
+        """ See IFilesystemExporter.
+        """
+        export_context.writeDataFile('%s.csv' % self.context.getId(),
+                                     self.context.as_csv(),
+                                     'text/comma-separated-values',
+                                     subdir,
+                                    )
+
+    def listExportableItems(self):
+        """ See IFilesystemExporter.
+        """
+        return ()
+
+    def import_(self, import_context, subdir):
+        """ See IFilesystemImporter.
+        """
+        cid = self.context.getId()
+        data = import_context.readDataFile('%s.csv' % cid, subdir)
+        if data is None:
+            import_context.note('CSAFA',
+                                'no .csv file for %s/%s' % (subdir, cid))
+        else:
+            stream = StringIO(data)
+            self.context.put_csv(stream)
+
+class INIAwareFileAdapter(object):
+    """ Exporter/importer for content whose "natural" representation is CSV.
+    """
+    implements(IFilesystemExporter, IFilesystemImporter)
+
+    def __init__(self, context):
+        self.context = context
+
+    def export(self, export_context, subdir):
+        """ See IFilesystemExporter.
+        """
+        export_context.writeDataFile('%s.ini' % self.context.getId(),
+                                     self.context.as_ini(),
+                                     'text/plain',
+                                     subdir,
+                                    )
+
+    def listExportableItems(self):
+        """ See IFilesystemExporter.
+        """
+        return ()
+
+    def import_(self, import_context, subdir):
+        """ See IFilesystemImporter.
+        """
+        cid = self.context.getId()
+        data = import_context.readDataFile('%s.ini' % cid, subdir)
+        if data is None:
+            import_context.note('SGAIFA',
+                                'no .ini file for %s/%s' % (subdir, cid))
+        else:
+            self.context.put_ini(data)
+
+
+class FauxDAVRequest:
+
+    def __init__(self, **kw):
+        self._data = {}
+        self._headers = {}
+        self._data.update(kw)
+
+    def __getitem__(self, key):
+        return self._data[key]
+
+    def get(self, key, default=None):
+        return self._data.get(key, default)
+
+    def get_header(self, key, default=None):
+        return self._headers.get(key, default)
+
+class FauxDAVResponse:
+    def setHeader(self, key, value, lock=False):
+        pass  # stub this out to mollify webdav.Resource
+    def setStatus(self, value, reason=None):
+        pass  # stub this out to mollify webdav.Resource
+
+class DAVAwareFileAdapter(object):
+    """ Exporter/importer for content who handle their own FTP / DAV PUTs.
+    """
+    implements(IFilesystemExporter, IFilesystemImporter)
+
+    def __init__(self, context):
+        self.context = context
+
+    def export(self, export_context, subdir):
+        """ See IFilesystemExporter.
+        """
+        export_context.writeDataFile('%s' % self.context.getId(),
+                                     self.context.manage_FTPget(),
+                                     'text/plain',
+                                     subdir,
+                                    )
+
+    def listExportableItems(self):
+        """ See IFilesystemExporter.
+        """
+        return ()
+
+    def import_(self, import_context, subdir):
+        """ See IFilesystemImporter.
+        """
+        cid = self.context.getId()
+        data = import_context.readDataFile('%s' % cid, subdir)
+        if data is None:
+            import_context.note('SGAIFA',
+                                'no .ini file for %s/%s' % (subdir, cid))
+        else:
+            request = FauxDAVRequest(BODY=data, BODYFILE=data)
+            response = FauxDAVResponse()
+            self.context.PUT(request, response)

Copied: CMF/trunk/CMFCore/exportimport/cookieauth.py (from rev 39486, CMF/trunk/CMFCore/nodeadapters.py)
===================================================================
--- CMF/trunk/CMFCore/nodeadapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/CMFCore/exportimport/cookieauth.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -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.
+#
+##############################################################################
+"""Cookie crumbler node adapters.
+
+$Id$
+"""
+
+from Products.GenericSetup.interfaces import PURGE
+from Products.GenericSetup.utils import NodeAdapterBase
+from Products.GenericSetup.utils import PropertyManagerHelpers
+
+from Products.CMFCore.interfaces import ICookieCrumbler
+
+
+class CookieCrumblerNodeAdapter(NodeAdapterBase, PropertyManagerHelpers):
+
+    """Node im- and exporter for CookieCrumbler.
+    """
+
+    __used_for__ = ICookieCrumbler
+
+    def exportNode(self, doc):
+        """Export the object as a DOM node.
+        """
+        self._doc = doc
+        node = self._getObjectNode('object')
+        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)

Added: CMF/trunk/CMFCore/exportimport/tests/__init__.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/tests/__init__.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/CMFCore/exportimport/tests/__init__.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -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.
+#
+##############################################################################
+"""CMFCore export / import support unit tests.
+
+$Id$
+"""


Property changes on: CMF/trunk/CMFCore/exportimport/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Copied: CMF/trunk/CMFCore/exportimport/tests/conformance.py (from rev 39486, CMF/trunk/CMFCore/tests/conformance.py)
===================================================================
--- CMF/trunk/CMFCore/tests/conformance.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/CMFCore/exportimport/tests/conformance.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" Mix-in classes for testing interface conformance.
+
+$Id$
+"""
+
+class ConformsToISimpleItem:
+
+    def test_conforms_to_Five_ISimpleItem(self):
+        from zope.interface.verify import verifyClass
+        from Products.Five.interfaces import ISimpleItem
+
+        verifyClass(ISimpleItem, self._getTargetClass())
+
+class ConformsToIINIAware:
+
+    def test_conforms_to_IINIAware(self):
+        from zope.interface.verify import verifyClass
+        from Products.CMFCore.interfaces import IINIAware
+
+        verifyClass(IINIAware, self._getTargetClass())
+
+class ConformsToICSVAware:
+
+    def test_conforms_to_ICSVAware(self):
+        from zope.interface.verify import verifyClass
+        from Products.CMFCore.interfaces import ICSVAware
+
+        verifyClass(ICSVAware, self._getTargetClass())
+
+class ConformsToIFilesystemExporter:
+    """ Mix-in for test cases whose target class implements IFilesystemExporter.
+    """
+    def test_conforms_to_IFilesystemExporter(self):
+        from zope.interface.verify import verifyClass
+        from Products.CMFCore.interfaces import IFilesystemExporter
+
+        verifyClass(IFilesystemExporter, self._getTargetClass())
+
+class ConformsToIFilesystemImporter:
+    """ Mix-in for test cases whose target class implements IFilesystemImporter.
+    """
+    def test_conforms_to_IFilesystemImporter(self):
+        from zope.interface.verify import verifyClass
+        from Products.CMFCore.interfaces import IFilesystemImporter
+
+        verifyClass(IFilesystemImporter, self._getTargetClass())

Copied: CMF/trunk/CMFCore/exportimport/tests/test_actions.py (from rev 39486, CMF/trunk/CMFCore/tests/test_nodeadapters.py)
===================================================================
--- CMF/trunk/CMFCore/tests/test_nodeadapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/CMFCore/exportimport/tests/test_actions.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,164 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Actions tool node adapter unit tests.
+
+$Id$
+"""
+
+import unittest
+import Testing
+import Zope2
+Zope2.startup()
+
+import Products.CMFCore.exportimport
+import Products.Five
+from Products.Five import zcml
+from zope.app.tests.placelesssetup import PlacelessSetup
+
+from Products.CMFCore.tests.base.dummy import DummySite
+from Products.GenericSetup.testing import NodeAdapterTestCase
+
+
+_ACTION_XML = """\
+<object name="foo_action" meta_type="CMF Action">
+ <property name="title">Foo</property>
+ <property name="description"></property>
+ <property name="url_expr">string:${object_url}/foo</property>
+ <property name="icon_expr"></property>
+ <property name="available_expr">python:1</property>
+ <property name="permissions"/>
+ <property name="visible">True</property>
+</object>
+"""
+
+_ACTIONCATEGORY_XML = """\
+<object name="foo_category" meta_type="CMF Action Category">
+ <property name="title"></property>
+ <object name="foo_action" meta_type="CMF Action">
+  <property name="title"></property>
+  <property name="description"></property>
+  <property name="url_expr"></property>
+  <property name="icon_expr"></property>
+  <property name="available_expr"></property>
+  <property name="permissions"/>
+  <property name="visible">True</property>
+ </object>
+</object>
+"""
+
+_ACTIONSTOOL_XML = """\
+<object name="portal_actions" meta_type="CMF Actions Tool"
+   xmlns:i18n="http://xml.zope.org/namespaces/i18n">
+ <action-provider name="portal_actions"/>
+ <object name="foo_category" meta_type="CMF Action Category">
+  <property name="title"></property>
+  <object name="foo_action" meta_type="CMF Action" i18n:domain="foo_domain">
+   <property name="title" i18n:translate=""></property>
+   <property name="description" i18n:translate=""></property>
+   <property name="url_expr"></property>
+   <property name="icon_expr"></property>
+   <property name="available_expr"></property>
+   <property name="permissions"/>
+   <property name="visible">True</property>
+  </object>
+ </object>
+</object>
+"""
+
+
+class ActionNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.CMFCore.exportimport.actions import ActionNodeAdapter
+
+        return ActionNodeAdapter
+
+    def _populate(self, obj):
+        obj._setPropValue('title', 'Foo')
+        obj._setPropValue('url_expr', 'string:${object_url}/foo')
+        obj._setPropValue('available_expr', 'python:1')
+
+    def setUp(self):
+        from Products.CMFCore.ActionInformation import Action
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml', Products.CMFCore.exportimport)
+
+        self._obj = Action('foo_action')
+        self._XML = _ACTION_XML
+
+
+class ActionCategoryNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.CMFCore.exportimport.actions \
+                import ActionCategoryNodeAdapter
+
+        return ActionCategoryNodeAdapter
+
+    def _populate(self, obj):
+        from Products.CMFCore.ActionInformation import Action
+
+        obj._setObject('foo_action', Action('foo_action'))
+
+    def setUp(self):
+        from Products.CMFCore.ActionInformation import ActionCategory
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml', Products.CMFCore.exportimport)
+
+        self._obj = ActionCategory('foo_category')
+        self._XML = _ACTIONCATEGORY_XML
+
+
+class ActionsToolNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.CMFCore.exportimport.actions \
+                import ActionsToolNodeAdapter
+
+        return ActionsToolNodeAdapter
+
+    def _populate(self, obj):
+        from Products.CMFCore.ActionInformation import Action
+        from Products.CMFCore.ActionInformation import ActionCategory
+
+        obj._setObject('foo_category', ActionCategory('foo_category'))
+        obj.action_providers = ('portal_actions',)
+        obj.foo_category._setObject('foo_action', Action('foo_action'))
+        obj.foo_category.foo_action.i18n_domain = 'foo_domain'
+
+    def setUp(self):
+        from Products.CMFCore.ActionsTool import ActionsTool
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml', Products.CMFCore.exportimport)
+
+        site = DummySite('site')
+        site._setObject('portal_actions', ActionsTool('portal_actions'))
+        self._obj = site.portal_actions
+        self._XML = _ACTIONSTOOL_XML
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(ActionNodeAdapterTests),
+        unittest.makeSuite(ActionCategoryNodeAdapterTests),
+        unittest.makeSuite(ActionsToolNodeAdapterTests),
+        ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Copied: CMF/trunk/CMFCore/exportimport/tests/test_content.py (from rev 39486, CMF/trunk/CMFCore/tests/test_exportimport.py)
===================================================================
--- CMF/trunk/CMFCore/tests/test_exportimport.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/CMFCore/exportimport/tests/test_content.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,870 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Filesystem exporter / importer adapter unit tests.
+
+$Id$
+"""
+
+import unittest
+import Testing
+
+from csv import reader
+from ConfigParser import ConfigParser
+from StringIO import StringIO
+
+from zope.app.tests.placelesssetup import PlacelessSetup
+
+from Products.GenericSetup.tests.common import DummyExportContext
+from Products.GenericSetup.tests.common import DummyImportContext
+
+from conformance import ConformsToIFilesystemExporter
+from conformance import ConformsToIFilesystemImporter
+
+
+class SiteStructureExporterTests(PlacelessSetup,
+                                 unittest.TestCase,
+                                ):
+
+    def _getExporter(self):
+        from Products.CMFCore.exportimport.content import exportSiteStructure
+        return exportSiteStructure
+
+    def _getImporter(self):
+        from Products.CMFCore.exportimport.content import importSiteStructure
+        return importSiteStructure
+
+    def _makeSetupTool(self):
+        from Products.GenericSetup.tool import SetupTool
+        return SetupTool('portal_setup')
+
+    def _setUpAdapters(self):
+        from zope.app.tests import ztapi
+        #from OFS.Image import File
+
+        from Products.CMFCore.interfaces import IFilesystemExporter
+        from Products.CMFCore.interfaces import IFilesystemImporter
+        from Products.CMFCore.interfaces import IFolderish
+        from Products.CMFCore.interfaces import ICSVAware
+        from Products.CMFCore.interfaces import IINIAware
+
+        from Products.CMFCore.exportimport.content import \
+             StructureFolderWalkingAdapter
+        from Products.CMFCore.exportimport.content import \
+             CSVAwareFileAdapter
+        from Products.CMFCore.exportimport.content import \
+             INIAwareFileAdapter
+
+        #from Products.CMFCore.exportimport.content import \
+        #        OFSFileAdapter
+
+        ztapi.provideAdapter(IFolderish,
+                             IFilesystemExporter,
+                             StructureFolderWalkingAdapter,
+                            )
+
+        ztapi.provideAdapter(IFolderish,
+                             IFilesystemImporter,
+                             StructureFolderWalkingAdapter,
+                            )
+
+        ztapi.provideAdapter(ICSVAware,
+                             IFilesystemExporter,
+                             CSVAwareFileAdapter,
+                            )
+
+        ztapi.provideAdapter(ICSVAware,
+                             IFilesystemImporter,
+                             CSVAwareFileAdapter,
+                            )
+
+        ztapi.provideAdapter(IINIAware,
+                             IFilesystemExporter,
+                             INIAwareFileAdapter,
+                            )
+
+        ztapi.provideAdapter(IINIAware,
+                             IFilesystemImporter,
+                             INIAwareFileAdapter,
+                            )
+
+
+    def test_export_empty_site(self):
+        self._setUpAdapters()
+        site = _makeFolder('site', site_folder=True)
+        site.title = 'test_export_empty_site'
+        site.description = 'Testing export of an empty site.'
+        context = DummyExportContext(site)
+        exporter = self._getExporter()
+        exporter(context)
+
+        self.assertEqual(len(context._wrote), 2)
+        filename, text, content_type = context._wrote[0]
+        self.assertEqual(filename, 'structure/.objects')
+        self.assertEqual(content_type, 'text/comma-separated-values')
+
+        objects = [x for x in reader(StringIO(text))]
+        self.assertEqual(len(objects), 0)
+
+        filename, text, content_type = context._wrote[1]
+        self.assertEqual(filename, 'structure/.properties')
+        self.assertEqual(content_type, 'text/plain')
+
+        parser = ConfigParser()
+        parser.readfp(StringIO(text))
+
+        self.assertEqual(parser.get('DEFAULT', 'Title'),
+                         site.title)
+        self.assertEqual(parser.get('DEFAULT', 'Description'),
+                         site.description)
+
+    def test_export_empty_site_with_setup_tool(self):
+        self._setUpAdapters()
+        site = _makeFolder('site', site_folder=True)
+        site._setObject('setup_tool', self._makeSetupTool())
+        site.title = 'test_export_empty_site_with_setup_tool'
+        site.description = 'Testing export of an empty site with setup tool.'
+        context = DummyExportContext(site)
+        exporter = self._getExporter()
+        exporter(context)
+
+        self.assertEqual(len(context._wrote), 2)
+        filename, text, content_type = context._wrote[0]
+        self.assertEqual(filename, 'structure/.objects')
+        self.assertEqual(content_type, 'text/comma-separated-values')
+
+        objects = [x for x in reader(StringIO(text))]
+        self.assertEqual(len(objects), 0)
+
+        filename, text, content_type = context._wrote[1]
+        self.assertEqual(filename, 'structure/.properties')
+        self.assertEqual(content_type, 'text/plain')
+
+        parser = ConfigParser()
+        parser.readfp(StringIO(text))
+
+        self.assertEqual(parser.get('DEFAULT', 'Title'),
+                         site.title)
+        self.assertEqual(parser.get('DEFAULT', 'Description'),
+                         site.description)
+
+    def test_export_site_with_non_exportable_simple_items(self):
+        self._setUpAdapters()
+        ITEM_IDS = ('foo', 'bar', 'baz')
+
+        site = _makeFolder('site', site_folder=True)
+        site.title = 'AAA'
+        site.description = 'BBB'
+        for id in ITEM_IDS:
+            site._setObject(id, _makeItem(id))
+
+        context = DummyExportContext(site)
+        exporter = self._getExporter()
+        exporter(context)
+
+        self.assertEqual(len(context._wrote), 2)
+        filename, text, content_type = context._wrote[0]
+        self.assertEqual(filename, 'structure/.objects')
+        self.assertEqual(content_type, 'text/comma-separated-values')
+
+        objects = [x for x in reader(StringIO(text))]
+        self.assertEqual(len(objects), 3)
+        for index in range(len(ITEM_IDS)):
+            self.assertEqual(objects[index][0], ITEM_IDS[index])
+            self.assertEqual(objects[index][1], TEST_CONTENT)
+
+        filename, text, content_type = context._wrote[1]
+        self.assertEqual(filename, 'structure/.properties')
+        self.assertEqual(content_type, 'text/plain')
+        parser = ConfigParser()
+        parser.readfp(StringIO(text))
+
+        self.assertEqual(parser.get('DEFAULT', 'title'), 'AAA')
+        self.assertEqual(parser.get('DEFAULT', 'description'), 'BBB')
+
+    def test_export_site_with_exportable_simple_items(self):
+        self._setUpAdapters()
+        ITEM_IDS = ('foo', 'bar', 'baz')
+
+        site = _makeFolder('site', site_folder=True)
+        site.title = 'AAA'
+        site.description = 'BBB'
+        for id in ITEM_IDS:
+            site._setObject(id, _makeINIAware(id))
+
+        context = DummyExportContext(site)
+        exporter = self._getExporter()
+        exporter(context)
+
+        self.assertEqual(len(context._wrote), 2 + len(ITEM_IDS))
+        filename, text, content_type = context._wrote[0]
+        self.assertEqual(filename, 'structure/.objects')
+        self.assertEqual(content_type, 'text/comma-separated-values')
+
+        objects = [x for x in reader(StringIO(text))]
+        self.assertEqual(len(objects), 3)
+        for index in range(len(ITEM_IDS)):
+            self.assertEqual(objects[index][0], ITEM_IDS[index])
+            self.assertEqual(objects[index][1], TEST_INI_AWARE)
+
+            filename, text, content_type = context._wrote[index+2]
+            self.assertEqual(filename, 'structure/%s.ini' % ITEM_IDS[index])
+            object = site._getOb(ITEM_IDS[index])
+            self.assertEqual(text.strip(),
+                             object.as_ini().strip())
+            self.assertEqual(content_type, 'text/plain')
+
+        filename, text, content_type = context._wrote[1]
+        self.assertEqual(filename, 'structure/.properties')
+        self.assertEqual(content_type, 'text/plain')
+        parser = ConfigParser()
+        parser.readfp(StringIO(text))
+
+        self.assertEqual(parser.get('DEFAULT', 'title'), 'AAA')
+        self.assertEqual(parser.get('DEFAULT', 'description'), 'BBB')
+
+    def test_export_site_with_subfolders(self):
+        self._setUpAdapters()
+        FOLDER_IDS = ('foo', 'bar', 'baz')
+
+        site = _makeFolder('site', site_folder=True)
+        site.title = 'AAA'
+        site.description = 'BBB'
+        for id in FOLDER_IDS:
+            folder = _makeFolder(id)
+            folder.title = 'Title: %s' % id
+            folder.description = 'xyzzy'
+            site._setObject(id, folder)
+
+        context = DummyExportContext(site)
+        exporter = self._getExporter()
+        exporter(context)
+
+        self.assertEqual(len(context._wrote), 2 + (2 *len(FOLDER_IDS)))
+        filename, text, content_type = context._wrote[0]
+        self.assertEqual(filename, 'structure/.objects')
+        self.assertEqual(content_type, 'text/comma-separated-values')
+
+        objects = [x for x in reader(StringIO(text))]
+        self.assertEqual(len(objects), 3)
+
+        for index in range(len(FOLDER_IDS)):
+            id = FOLDER_IDS[index]
+            self.assertEqual(objects[index][0], id)
+            self.assertEqual(objects[index][1], TEST_FOLDER)
+
+            filename, text, content_type = context._wrote[2 + (2 * index)]
+            self.assertEqual(filename, '/'.join(('structure', id, '.objects')))
+            self.assertEqual(content_type, 'text/comma-separated-values')
+            subobjects = [x for x in reader(StringIO(text))]
+            self.assertEqual(len(subobjects), 0)
+
+            filename, text, content_type = context._wrote[2 + (2 * index) + 1]
+            self.assertEqual(filename,
+                             '/'.join(('structure', id, '.properties')))
+            self.assertEqual(content_type, 'text/plain')
+            parser = ConfigParser()
+            parser.readfp(StringIO(text))
+
+            self.assertEqual(parser.get('DEFAULT', 'Title'), 'Title: %s' % id)
+
+        filename, text, content_type = context._wrote[1]
+        self.assertEqual(filename, 'structure/.properties')
+        self.assertEqual(content_type, 'text/plain')
+
+        parser = ConfigParser()
+        parser.readfp(StringIO(text))
+
+        self.assertEqual(parser.get('DEFAULT', 'title'), 'AAA')
+        self.assertEqual(parser.get('DEFAULT', 'description'), 'BBB')
+
+    def test_export_site_with_csvaware(self):
+        self._setUpAdapters()
+
+        site = _makeFolder('site', site_folder=True)
+        site.title = 'test_export_site_with_csvaware'
+        site.description = 'Testing export of an site with CSV-aware content.'
+
+        site._setObject('aware', _makeCSVAware('aware'))
+
+        context = DummyExportContext(site)
+        exporter = self._getExporter()
+        exporter(context)
+
+        self.assertEqual(len(context._wrote), 3)
+        filename, text, content_type = context._wrote[0]
+        self.assertEqual(filename, 'structure/.objects')
+        self.assertEqual(content_type, 'text/comma-separated-values')
+
+        objects = [x for x in reader(StringIO(text))]
+        self.assertEqual(len(objects), 1)
+        self.assertEqual(objects[0][0], 'aware')
+        self.assertEqual(objects[0][1], TEST_CSV_AWARE)
+
+        filename, text, content_type = context._wrote[1]
+        self.assertEqual(filename, 'structure/.properties')
+        self.assertEqual(content_type, 'text/plain')
+
+        parser = ConfigParser()
+        parser.readfp(StringIO(text))
+
+        self.assertEqual(parser.get('DEFAULT', 'Title'),
+                                    site.title)
+        self.assertEqual(parser.get('DEFAULT', 'Description'),
+                                    site.description)
+
+        filename, text, content_type = context._wrote[2]
+        self.assertEqual(filename, 'structure/aware.csv')
+        self.assertEqual(content_type, 'text/comma-separated-values')
+        rows = [x for x in reader(StringIO(text))]
+        self.assertEqual(len(rows), 2)
+        self.assertEqual(rows[0][0], 'one')
+        self.assertEqual(rows[0][1], 'two')
+        self.assertEqual(rows[0][2], 'three')
+        self.assertEqual(rows[1][0], 'four')
+        self.assertEqual(rows[1][1], 'five')
+        self.assertEqual(rows[1][2], 'six')
+
+    def test_import_empty_site(self):
+        self._setUpAdapters()
+        site = _makeFolder('site', site_folder=True)
+        context = DummyImportContext(site)
+        context._files['structure/.objects'] = ''
+        importer = self._getImporter()
+        self.assertEqual(len(site.objectIds()), 0)
+        importer(context)
+        self.assertEqual(len(site.objectIds()), 0)
+
+    def test_import_empty_site_with_setup_tool(self):
+        self._setUpAdapters()
+        site = _makeFolder('site', site_folder=True)
+        site._setObject('setup_tool', self._makeSetupTool())
+        context = DummyImportContext(site)
+        importer = self._getImporter()
+
+        self.assertEqual(len(site.objectIds()), 1)
+        self.assertEqual(site.objectIds()[0], 'setup_tool')
+        importer(context)
+        self.assertEqual(len(site.objectIds()), 1)
+        self.assertEqual(site.objectIds()[0], 'setup_tool')
+
+    def test_import_site_with_subfolders(self):
+        self._setUpAdapters()
+        FOLDER_IDS = ('foo', 'bar', 'baz')
+
+        site = _makeFolder('site', site_folder=True)
+
+        context = DummyImportContext(site)
+
+        for id in FOLDER_IDS:
+            context._files['structure/%s/.objects' % id] = ''
+            context._files['structure/%s/.properties' % id] = (
+                _PROPERTIES_TEMPLATE % id )
+
+        _ROOT_OBJECTS = '\n'.join(['%s,%s' % (id, TEST_FOLDER)
+                                        for id in FOLDER_IDS])
+
+        context._files['structure/.objects'] = _ROOT_OBJECTS
+        context._files['structure/.properties'] = (
+                _PROPERTIES_TEMPLATE % 'Test Site')
+
+        importer = self._getImporter()
+        importer(context)
+
+        content = site.contentValues()
+        self.assertEqual(len(content), len(FOLDER_IDS))
+
+    def test_import_site_with_subitems(self):
+        self._setUpAdapters()
+        ITEM_IDS = ('foo', 'bar', 'baz')
+
+        site = _makeFolder('site', site_folder=True)
+
+        context = DummyImportContext(site)
+        # We want to add 'baz' to 'foo', without losing 'bar'
+        context._files['structure/.objects'] = '\n'.join(
+                            ['%s,%s' % (x, TEST_INI_AWARE) for x in ITEM_IDS])
+        for index in range(len(ITEM_IDS)):
+            id = ITEM_IDS[index]
+            context._files[
+                    'structure/%s.ini' % id] = KNOWN_INI % ('Title: %s' % id,
+                                                            'xyzzy',
+                                                           )
+        importer = self._getImporter()
+        importer(context)
+
+        after = site.objectIds()
+        self.assertEqual(len(after), len(ITEM_IDS))
+        for found_id, expected_id in zip(after, ITEM_IDS):
+            self.assertEqual(found_id, expected_id)
+
+    def test_import_site_with_subitem_unknown_portal_type(self):
+        self._setUpAdapters()
+        ITEM_IDS = ('foo', 'bar', 'baz')
+
+        site = _makeFolder('site', site_folder=True)
+
+        context = DummyImportContext(site)
+        # We want to add 'baz' to 'foo', without losing 'bar'
+        context._files['structure/.objects'] = '\n'.join(
+                                ['%s,Unknown Type' % x for x in ITEM_IDS])
+        for index in range(len(ITEM_IDS)):
+            id = ITEM_IDS[index]
+            context._files[
+                    'structure/%s.ini' % id] = KNOWN_INI % ('Title: %s' % id,
+                                                            'xyzzy',
+                                                           )
+
+        importer = self._getImporter()
+        importer(context)
+
+        after = site.objectIds()
+        self.assertEqual(len(after), 0)
+        self.assertEqual(len(context._notes), len(ITEM_IDS))
+        for component, message in context._notes:
+            self.assertEqual(component, 'SFWA')
+            self.failUnless(message.startswith("Couldn't make"))
+
+    def test_import_site_with_subitems_and_no_preserve(self):
+        self._setUpAdapters()
+        ITEM_IDS = ('foo', 'bar', 'baz')
+
+        site = _makeFolder('site', site_folder=True)
+        for id in ITEM_IDS:
+            site._setObject(id, _makeItem(id))
+
+        context = DummyImportContext(site)
+        # We want to add 'baz' to 'foo', without losing 'bar'
+        context._files['structure/.objects'] = ''
+
+        importer = self._getImporter()
+        importer(context)
+
+        self.assertEqual(len(site.objectIds()), 0)
+
+    def test_import_site_with_subitemss_and_preserve(self):
+        self._setUpAdapters()
+        ITEM_IDS = ('foo', 'bar', 'baz')
+
+        site = _makeFolder('site', site_folder=True)
+        for id in ITEM_IDS:
+            site._setObject(id, _makeItem(id))
+
+        context = DummyImportContext(site)
+        # We want to add 'baz' to 'foo', without losing 'bar'
+        context._files['structure/.objects'] = ''
+        context._files['structure/.preserve'] = '*'
+
+        importer = self._getImporter()
+        importer(context)
+
+        after = site.objectIds()
+        self.assertEqual(len(after), len(ITEM_IDS))
+        for i in range(len(ITEM_IDS)):
+            self.assertEqual(after[i], ITEM_IDS[i])
+
+    def test_import_site_with_subitemss_and_preserve_partial(self):
+        self._setUpAdapters()
+        ITEM_IDS = ('foo', 'bar', 'baz')
+
+        site = _makeFolder('site', site_folder=True)
+        for id in ITEM_IDS:
+            site._setObject(id, _makeItem(id))
+
+        context = DummyImportContext(site)
+        # We want to add 'baz' to 'foo', without losing 'bar'
+        context._files['structure/.objects'] = ''
+        context._files['structure/.preserve'] = 'b*'
+
+        importer = self._getImporter()
+        importer(context)
+
+        after = site.objectIds()
+        self.assertEqual(len(after), 2)
+        self.assertEqual(after[0], 'bar')
+        self.assertEqual(after[1], 'baz')
+
+    def test_import_site_with_subfolders_and_preserve(self):
+        self._setUpAdapters()
+
+        site = _makeFolder('site', site_folder=True)
+        site._setObject('foo', _makeFolder('foo'))
+        site.foo._setObject('bar', _makeFolder('bar'))
+
+        context = DummyImportContext(site)
+        # We want to add 'baz' to 'foo', without losing 'bar'
+        context._files['structure/.objects'] = 'foo,%s' % TEST_FOLDER
+        context._files['structure/.preserve'] = '*'
+        context._files['structure/foo/.objects'] = 'baz,%s' % TEST_FOLDER
+        context._files['structure/foo/.preserve'] = '*'
+        context._files['structure/foo/baz/.objects'] = ''
+
+        importer = self._getImporter()
+        importer(context)
+
+        self.assertEqual(len(site.objectIds()), 1)
+        self.assertEqual(site.objectIds()[0], 'foo')
+
+        self.assertEqual(len(site.foo.objectIds()), 2, site.foo.objectIds())
+        self.assertEqual(site.foo.objectIds()[0], 'bar')
+        self.assertEqual(site.foo.objectIds()[1], 'baz')
+
+
+class Test_globpattern(unittest.TestCase):
+
+    NAMELIST = ('foo', 'bar', 'baz', 'bam', 'qux', 'quxx', 'quxxx')
+
+    def _checkResults(self, globpattern, namelist, expected):
+        from Products.CMFCore.exportimport.content import _globtest
+        found = _globtest(globpattern, namelist)
+        self.assertEqual(len(found), len(expected))
+        for found_item, expected_item in zip(found, expected):
+            self.assertEqual(found_item, expected_item)
+
+    def test_star(self):
+        self._checkResults('*', self.NAMELIST, self.NAMELIST)
+
+    def test_simple(self):
+        self._checkResults('b*', self.NAMELIST,
+                            [x for x in self.NAMELIST if x.startswith('b')])
+
+    def test_multiple(self):
+        self._checkResults('b*\n*x', self.NAMELIST,
+                            [x for x in self.NAMELIST
+                                if x.startswith('b') or x.endswith('x')])
+
+
+class CSVAwareFileAdapterTests(unittest.TestCase,
+                               ConformsToIFilesystemExporter,
+                               ConformsToIFilesystemImporter,
+                              ):
+
+    def _getTargetClass(self):
+        from Products.CMFCore.exportimport.content import CSVAwareFileAdapter
+        return CSVAwareFileAdapter
+
+    def _makeOne(self, context, *args, **kw):
+        return self._getTargetClass()(context, *args, **kw)
+
+    def _makeCSVAware(self, sheet_id, csv=''):
+        class Foo:
+            def getId(self):
+                return self._id
+            def as_csv(self):
+                return self.csv
+            def put_csv(self, stream):
+                self.new_csv = stream.getvalue()
+
+        foo = Foo()
+        foo._id = sheet_id
+        foo.csv = csv
+        foo.new_csv = None
+
+        return foo
+
+
+    def test_export_with_known_CSV(self):
+        KNOWN_CSV = """\
+one,two,three
+four,five,six
+"""
+        sheet = self._makeCSVAware('config', KNOWN_CSV)
+
+        adapter = self._makeOne(sheet)
+        context = DummyExportContext(None)
+        adapter.export(context, 'subpath/to/sheet')
+
+        self.assertEqual(len(context._wrote), 1)
+        filename, text, content_type = context._wrote[0]
+        self.assertEqual(filename, 'subpath/to/sheet/config.csv')
+        self.assertEqual(content_type, 'text/comma-separated-values')
+
+        self.assertEqual(text.strip(), KNOWN_CSV.strip())
+
+    def test_import_with_known_CSV(self):
+        ORIG_CSV = """\
+one,two,three
+four,five,six
+"""
+        NEW_CSV = """\
+four,five,six
+one,two,three
+"""
+        sheet = self._makeCSVAware('config', ORIG_CSV)
+
+        adapter = self._makeOne(sheet)
+        context = DummyImportContext(None)
+        context._files['subpath/to/sheet/config.csv'] = NEW_CSV
+        adapter.import_(context, 'subpath/to/sheet')
+
+        self.assertEqual(sheet.new_csv.strip(), NEW_CSV.strip())
+
+
+_PROPERTIES_TEMPLATE = """
+[DEFAULT]
+Title = %s
+Description = This is a test
+"""
+
+class INIAwareFileAdapterTests(unittest.TestCase,
+                               ConformsToIFilesystemExporter,
+                               ConformsToIFilesystemImporter,
+                               ):
+
+    def _getTargetClass(self):
+        from Products.CMFCore.exportimport.content import INIAwareFileAdapter
+        return INIAwareFileAdapter
+
+    def _makeOne(self, context, *args, **kw):
+        return self._getTargetClass()(context, *args, **kw)
+
+    def test_export_ini_file(self):
+        ini_file = _makeINIAware('ini_file.html')
+        adapter = self._makeOne(ini_file)
+        context = DummyExportContext(None)
+        adapter.export(context, 'subpath/to')
+
+        self.assertEqual(len(context._wrote), 1)
+        filename, text, content_type = context._wrote[0]
+        self.assertEqual(filename, 'subpath/to/ini_file.html.ini')
+        self.assertEqual(content_type, 'text/plain')
+
+        self.assertEqual(text.strip(), ini_file.as_ini().strip())
+
+    def test_import_ini_file(self):
+        ini_file = _makeINIAware('ini_file.html')
+        adapter = self._makeOne(ini_file)
+        context = DummyImportContext(None)
+        context._files['subpath/to/ini_file.html.ini'] = (
+                        KNOWN_INI % ('Title: ini_file', 'abc'))
+
+        adapter.import_(context, 'subpath/to')
+        text = ini_file._was_put
+        parser = ConfigParser()
+        parser.readfp(StringIO(text))
+        self.assertEqual(parser.get('DEFAULT', 'title'), 'Title: ini_file')
+        self.assertEqual(parser.get('DEFAULT', 'description'), 'abc')
+
+
+class DAVAwareFileAdapterTests(unittest.TestCase,
+                               ConformsToIFilesystemExporter,
+                               ConformsToIFilesystemImporter,
+                               ):
+
+    def _getTargetClass(self):
+        from Products.CMFCore.exportimport.content import DAVAwareFileAdapter
+        return DAVAwareFileAdapter
+
+    def _makeOne(self, context, *args, **kw):
+        return self._getTargetClass()(context, *args, **kw)
+
+    def test_export_dav_file(self):
+        dav_file = _makeDAVAware('dav_file.html')
+        adapter = self._makeOne(dav_file)
+        context = DummyExportContext(None)
+        adapter.export(context, 'subpath/to')
+
+        self.assertEqual(len(context._wrote), 1)
+        filename, text, content_type = context._wrote[0]
+        self.assertEqual(filename, 'subpath/to/dav_file.html')
+        self.assertEqual(content_type, 'text/plain')
+        self.assertEqual(text.strip(), dav_file.manage_FTPget().strip())
+
+    def test_import_dav_file(self):
+        VALUES = ('Title: dav_file', 'Description: abc', 'body goes here')
+        dav_file = _makeDAVAware('dav_file.html')
+        adapter = self._makeOne(dav_file)
+        context = DummyImportContext(None)
+        context._files['subpath/to/dav_file.html'] = KNOWN_DAV % VALUES
+
+        adapter.import_(context, 'subpath/to')
+        text = dav_file._was_put == KNOWN_DAV % VALUES
+
+
+TEST_CSV_AWARE = 'Test CSV Aware'
+KNOWN_CSV = """\
+one,two,three
+four,five,six
+"""
+
+def _makeCSVAware(id):
+    from OFS.SimpleItem import SimpleItem
+    from zope.interface import implements
+    from Products.CMFCore.interfaces import IDynamicType
+    from Products.CMFCore.interfaces import ICSVAware
+
+    class _TestCSVAware(SimpleItem):
+        implements(IDynamicType, ICSVAware)
+        _was_put = None
+        portal_type = TEST_CSV_AWARE
+
+        def getPortalTypeName(self):
+            return self.portal_type
+
+        def as_csv(self):
+            return KNOWN_CSV
+
+        def put_csv(self, text):
+            self._was_put = text
+
+    aware = _TestCSVAware()
+    aware._setId(id)
+
+    return aware
+
+
+TEST_INI_AWARE = 'Test INI Aware'
+KNOWN_INI = """\
+[DEFAULT]
+title = %s
+description = %s
+"""
+
+def _makeINIAware(id):
+    from OFS.SimpleItem import SimpleItem
+    from zope.interface import implements
+    from Products.CMFCore.interfaces import IDynamicType
+    from Products.CMFCore.interfaces import IINIAware
+
+    class _TestINIAware(SimpleItem):
+        implements(IDynamicType, IINIAware)
+        _was_put = None
+        title = 'INI title'
+        description = 'INI description'
+        portal_type = TEST_INI_AWARE
+
+        def getPortalTypeName(self):
+            return self.portal_type
+
+        def as_ini(self):
+            return KNOWN_INI % (self.title, self.description)
+
+        def put_ini(self, text):
+            self._was_put = text
+
+    aware = _TestINIAware()
+    aware._setId(id)
+
+    return aware
+
+
+TEST_DAV_AWARE = 'Test DAV Aware'
+KNOWN_DAV = """\
+Title: %s
+Description: %s
+
+%s
+"""
+
+def _makeDAVAware(id):
+    from OFS.SimpleItem import SimpleItem
+    from zope.interface import implements
+    from Products.CMFCore.interfaces import IDynamicType
+    from Products.CMFCore.interfaces import IDAVAware
+
+    class _TestDAVAware(SimpleItem):
+        implements(IDynamicType, IDAVAware)
+        _was_put = None
+        title = 'DAV title'
+        description = 'DAV description'
+        body = 'DAV body'
+        portal_type = TEST_DAV_AWARE
+
+        def getPortalTypeName(self):
+            return self.portal_type
+
+        def manage_FTPget(self):
+            return KNOWN_DAV % (self.title, self.description, self.body)
+
+        def PUT(self, REQUEST, RESPONSE):
+            self._was_put = REQUEST.get('BODY', '')
+
+    aware = _TestDAVAware()
+    aware._setId(id)
+
+    return aware
+
+
+TEST_CONTENT = 'Test Content'
+
+def _makeItem(self):
+    from OFS.SimpleItem import SimpleItem
+    from zope.interface import implements
+    from Products.CMFCore.interfaces import IDynamicType
+
+    class _TestContent(SimpleItem):
+        implements(IDynamicType)
+        portal_type = TEST_CONTENT
+
+        def getPortalTypeName(self):
+            return self.portal_type
+
+    aware = _TestContent()
+    aware._setId(id)
+
+    return aware
+
+
+TEST_FOLDER = 'Test Folder'
+
+def _makeFolder(id, site_folder=False):
+    from zope.interface import directlyProvides
+    from zope.interface import providedBy
+    from Products.CMFCore.PortalFolder import PortalFolder
+    from Products.CMFCore.interfaces import ISiteRoot
+    from Products.CMFCore.TypesTool import TypesTool
+    from Products.CMFCore.tests.base.dummy import DummyType
+
+    class _TypeInfo(DummyType):
+        def _getId(self):
+            return self._id
+        def constructInstance(self, container, id, *args, **kw):
+            portal_type = self._getId()
+            if portal_type == TEST_FOLDER:
+                content = PortalFolder(id)
+            elif portal_type == TEST_CONTENT:
+                content = _makeItem()
+                content._setId(id)
+            elif portal_type == TEST_INI_AWARE:
+                content = _makeINIAware(id)
+            elif portal_type == TEST_CSV_AWARE:
+                content = _makeCSVAware(id)
+            else:
+                raise ValueError, 'Ugh'
+            content.portal_type = portal_type
+            container._setObject(id, content)
+            return container._getOb(id)
+
+    folder = PortalFolder(id)
+    folder.portal_type = TEST_FOLDER
+    if site_folder:
+        directlyProvides(folder, ISiteRoot + providedBy(folder))
+        tool = folder.portal_types = TypesTool()
+        tool._setObject(TEST_CSV_AWARE, _TypeInfo(TEST_CSV_AWARE))
+        tool._setObject(TEST_INI_AWARE, _TypeInfo(TEST_INI_AWARE))
+        tool._setObject(TEST_CONTENT, _TypeInfo(TEST_CONTENT))
+        tool._setObject(TEST_FOLDER, _TypeInfo(TEST_FOLDER))
+
+    return folder
+
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(SiteStructureExporterTests))
+    suite.addTest(unittest.makeSuite(Test_globpattern))
+    suite.addTest(unittest.makeSuite(CSVAwareFileAdapterTests))
+    suite.addTest(unittest.makeSuite(INIAwareFileAdapterTests))
+    suite.addTest(unittest.makeSuite(DAVAwareFileAdapterTests))
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Copied: CMF/trunk/CMFCore/exportimport/tests/test_cookieauth.py (from rev 39486, CMF/trunk/CMFCore/tests/test_nodeadapters.py)
===================================================================
--- CMF/trunk/CMFCore/tests/test_nodeadapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/CMFCore/exportimport/tests/test_cookieauth.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,70 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Cookie crumbler node adapter unit tests.
+
+$Id$
+"""
+
+import unittest
+import Testing
+
+import Products.CMFCore.exportimport
+import Products.Five
+from Products.Five import zcml
+from zope.app.tests.placelesssetup import PlacelessSetup
+
+from Products.GenericSetup.testing import NodeAdapterTestCase
+
+
+_COOKIECRUMBLER_XML = """\
+<object name="foo_cookiecrumbler" meta_type="Cookie Crumbler">
+ <property name="auth_cookie">__ac</property>
+ <property name="name_cookie">__ac_name</property>
+ <property name="pw_cookie">__ac_password</property>
+ <property name="persist_cookie">__ac_persistent</property>
+ <property name="auto_login_page">login_form</property>
+ <property name="logout_page">logged_out</property>
+ <property name="unauth_page"></property>
+ <property name="local_cookie_path">False</property>
+ <property name="cache_header_value">private</property>
+ <property name="log_username">True</property>
+</object>
+"""
+
+
+class CookieCrumblerNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.CMFCore.exportimport.cookieauth \
+                import CookieCrumblerNodeAdapter
+
+        return CookieCrumblerNodeAdapter
+
+    def setUp(self):
+        from Products.CMFCore.CookieCrumbler import CookieCrumbler
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml', Products.CMFCore.exportimport)
+
+        self._obj = CookieCrumbler('foo_cookiecrumbler')
+        self._XML = _COOKIECRUMBLER_XML
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(CookieCrumblerNodeAdapterTests),
+        ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Deleted: CMF/trunk/CMFCore/exportimport.py
===================================================================
--- CMF/trunk/CMFCore/exportimport.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/CMFCore/exportimport.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,319 +0,0 @@
-""" CMFCore filesystem exporter / importer adapters.
-
-$Id$
-"""
-from csv import excel
-from csv import reader
-from csv import register_dialect
-from csv import writer
-from ConfigParser import ConfigParser
-import re
-from StringIO import StringIO
-
-from Acquisition import aq_inner
-from Acquisition import aq_parent
-
-from zope.interface import implements
-from zope.interface import directlyProvides
-
-from Products.GenericSetup.interfaces import ISetupTool
-from Products.GenericSetup.tool import SetupTool
-
-from Products.CMFCore.interfaces import IFilesystemExporter
-from Products.CMFCore.interfaces import IFilesystemImporter
-from Products.CMFCore.interfaces import ISiteRoot
-from Products.CMFCore.PortalFolder import PortalFolder
-from Products.CMFCore.utils import getToolByName
-
-#
-#   setup_tool handlers
-#
-def exportSiteStructure(context):
-    IFilesystemExporter(context.getSite()).export(context, 'structure')
-
-def importSiteStructure(context):
-    IFilesystemImporter(context.getSite()).import_(context, 'structure')
-
-
-#
-#   Filesystem export/import adapters
-#
-class StructureFolderWalkingAdapter(object):
-    """ Tree-walking exporter for "folderish" types.
-
-    Folderish instances are mapped to directories within the 'structure'
-    portion of the profile, where the folder's relative path within the site
-    corresponds to the path of its directory under 'structure'.
-
-    The subobjects of a folderish instance are enumerated in the '.objects'
-    file in the corresponding directory.  This file is a CSV file, with one
-    row per subobject, with the following wtructure::
-
-     "<subobject id>","<subobject portal_type>"
-
-    Subobjects themselves are represented as individual files or
-    subdirectories within the parent's directory.
-    """
-
-    implements(IFilesystemExporter, IFilesystemImporter)
-
-    def __init__(self, context):
-        self.context = context
-
-    def export(self, export_context, subdir):
-        """ See IFilesystemExporter.
-        """
-        # Enumerate exportable children
-        exportable = self.context.contentItems()
-        exportable = [x + (IFilesystemExporter(x, None),) for x in exportable]
-        exportable = [x for x in exportable if x[1] is not None]
-
-        stream = StringIO()
-        csv_writer = writer(stream)
-
-        for object_id, object, ignored in exportable:
-            csv_writer.writerow((object_id, object.getPortalTypeName()))
-
-        if not ISiteRoot.providedBy(self.context):
-            subdir = '%s/%s' % (subdir, self.context.getId())
-
-        export_context.writeDataFile('.objects',
-                                     text=stream.getvalue(),
-                                     content_type='text/comma-separated-values',
-                                     subdir=subdir,
-                                    )
-
-        parser = ConfigParser()
-
-        parser.set('DEFAULT', 'Title', self.context.Title())
-        parser.set('DEFAULT', 'Description', self.context.Description())
-        stream = StringIO()
-        parser.write(stream)
-
-        export_context.writeDataFile('.properties',
-                                    text=stream.getvalue(),
-                                    content_type='text/plain',
-                                    subdir=subdir,
-                                    )
-
-        for id, object in self.context.objectItems():
-
-            adapter = IFilesystemExporter(object, None)
-
-            if adapter is not None:
-                adapter.export(export_context, subdir)
-
-    def import_(self, import_context, subdir):
-        """ See IFilesystemImporter.
-        """
-        context = self.context
-        if not ISiteRoot.providedBy(context):
-            subdir = '%s/%s' % (subdir, context.getId())
-
-        preserve = import_context.readDataFile('.preserve', subdir)
-
-        prior = context.contentIds()
-
-        if not preserve:
-            preserve = []
-        else:
-            preserve = _globtest(preserve, prior)
-
-        for id in prior:
-            if id not in preserve:
-                context._delObject(id)
-
-        objects = import_context.readDataFile('.objects', subdir)
-        if objects is None:
-            return
-
-        dialect = 'excel'
-        stream = StringIO(objects)
-
-        rowiter = reader(stream, dialect)
-
-        existing = context.objectIds()
-
-        for object_id, portal_type in rowiter:
-
-            if object_id not in existing:
-                object = self._makeInstance(object_id, portal_type,
-                                            subdir, import_context)
-                if object is None:
-                    message = "Couldn't make instance: %s/%s" % (subdir,
-                                                                 object_id)
-                    import_context.note('SFWA', message)
-                    continue
-
-            wrapped = context._getOb(object_id)
-
-            IFilesystemImporter(wrapped).import_(import_context, subdir)
-
-    def _makeInstance(self, id, portal_type, subdir, import_context):
-
-        context = self.context
-        properties = import_context.readDataFile('.properties',
-                                                 '%s/%s' % (subdir, id))
-        tool = getToolByName(context, 'portal_types')
-
-        try:
-            tool.constructContent(portal_type, context, id)
-        except ValueError: # invalid type
-            return None
-
-        content = context._getOb(id)
-
-        if properties is not None:
-            lines = properties.splitlines()
-
-            stream = StringIO('\n'.join(lines))
-            parser = ConfigParser(defaults={'title': '', 'description': 'NONE'})
-            parser.readfp(stream)
-
-            title = parser.get('DEFAULT', 'title')
-            description = parser.get('DEFAULT', 'description')
-
-            content.setTitle(title)
-            content.setDescription(description)
-
-        return content
-
-
-def _globtest(globpattern, namelist):
-    """ Filter names in 'namelist', returning those which match 'globpattern'.
-    """
-    import re
-    pattern = globpattern.replace(".", r"\.")       # mask dots
-    pattern = pattern.replace("*", r".*")           # change glob sequence
-    pattern = pattern.replace("?", r".")            # change glob char
-    pattern = '|'.join(pattern.split())             # 'or' each line
-
-    compiled = re.compile(pattern)
-
-    return filter(compiled.match, namelist)
-
-
-class CSVAwareFileAdapter(object):
-    """ Adapter for content whose "natural" representation is CSV.
-    """
-    implements(IFilesystemExporter, IFilesystemImporter)
-
-    def __init__(self, context):
-        self.context = context
-
-    def export(self, export_context, subdir):
-        """ See IFilesystemExporter.
-        """
-        export_context.writeDataFile('%s.csv' % self.context.getId(),
-                                     self.context.as_csv(),
-                                     'text/comma-separated-values',
-                                     subdir,
-                                    )
-
-    def listExportableItems(self):
-        """ See IFilesystemExporter.
-        """
-        return ()
-
-    def import_(self, import_context, subdir):
-        """ See IFilesystemImporter.
-        """
-        cid = self.context.getId()
-        data = import_context.readDataFile('%s.csv' % cid, subdir)
-        if data is None:
-            import_context.note('CSAFA',
-                                'no .csv file for %s/%s' % (subdir, cid))
-        else:
-            stream = StringIO(data)
-            self.context.put_csv(stream)
-
-class INIAwareFileAdapter(object):
-    """ Exporter/importer for content whose "natural" representation is CSV.
-    """
-    implements(IFilesystemExporter, IFilesystemImporter)
-
-    def __init__(self, context):
-        self.context = context
-
-    def export(self, export_context, subdir):
-        """ See IFilesystemExporter.
-        """
-        export_context.writeDataFile('%s.ini' % self.context.getId(),
-                                     self.context.as_ini(),
-                                     'text/plain',
-                                     subdir,
-                                    )
-
-    def listExportableItems(self):
-        """ See IFilesystemExporter.
-        """
-        return ()
-
-    def import_(self, import_context, subdir):
-        """ See IFilesystemImporter.
-        """
-        cid = self.context.getId()
-        data = import_context.readDataFile('%s.ini' % cid, subdir)
-        if data is None:
-            import_context.note('SGAIFA',
-                                'no .ini file for %s/%s' % (subdir, cid))
-        else:
-            self.context.put_ini(data)
-
-
-class FauxDAVRequest:
-
-    def __init__(self, **kw):
-        self._data = {}
-        self._headers = {}
-        self._data.update(kw)
-
-    def __getitem__(self, key):
-        return self._data[key]
-
-    def get(self, key, default=None):
-        return self._data.get(key, default)
-
-    def get_header(self, key, default=None):
-        return self._headers.get(key, default)
-
-class FauxDAVResponse:
-    def setHeader(self, key, value, lock=False):
-        pass  # stub this out to mollify webdav.Resource
-    def setStatus(self, value, reason=None):
-        pass  # stub this out to mollify webdav.Resource
-
-class DAVAwareFileAdapter(object):
-    """ Exporter/importer for content who handle their own FTP / DAV PUTs.
-    """
-    implements(IFilesystemExporter, IFilesystemImporter)
-
-    def __init__(self, context):
-        self.context = context
-
-    def export(self, export_context, subdir):
-        """ See IFilesystemExporter.
-        """
-        export_context.writeDataFile('%s' % self.context.getId(),
-                                     self.context.manage_FTPget(),
-                                     'text/plain',
-                                     subdir,
-                                    )
-
-    def listExportableItems(self):
-        """ See IFilesystemExporter.
-        """
-        return ()
-
-    def import_(self, import_context, subdir):
-        """ See IFilesystemImporter.
-        """
-        cid = self.context.getId()
-        data = import_context.readDataFile('%s' % cid, subdir)
-        if data is None:
-            import_context.note('SGAIFA',
-                                'no .ini file for %s/%s' % (subdir, cid))
-        else:
-            request = FauxDAVRequest(BODY=data, BODYFILE=data)
-            response = FauxDAVResponse()
-            self.context.PUT(request, response)

Deleted: CMF/trunk/CMFCore/exportimport.zcml
===================================================================
--- CMF/trunk/CMFCore/exportimport.zcml	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/CMFCore/exportimport.zcml	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,55 +0,0 @@
-<configure
-  xmlns="http://namespaces.zope.org/zope"
-  xmlns:five="http://namespaces.zope.org/five"
-  i18n_domain="cmf"
-  >
-    
-  <adapter
-    for=".interfaces.IFolderish"
-    factory=".exportimport.StructureFolderWalkingAdapter"
-    provides=".interfaces.IFilesystemExporter"
-    />
-
-  <adapter
-    for=".interfaces.IFolderish"
-    factory=".exportimport.StructureFolderWalkingAdapter"
-    provides=".interfaces.IFilesystemImporter"
-    />
-
-  <adapter
-    for=".interfaces.ICSVAware"
-    factory=".exportimport.CSVAwareFileAdapter"
-    provides=".interfaces.IFilesystemExporter"
-    />
-
-  <adapter
-    for=".interfaces.ICSVAware"
-    factory=".exportimport.CSVAwareFileAdapter"
-    provides=".interfaces.IFilesystemImporter"
-    />
-
-  <adapter
-    for=".interfaces.IINIAware"
-    factory=".exportimport.INIAwareFileAdapter"
-    provides=".interfaces.IFilesystemExporter"
-    />
-
-  <adapter
-    for=".interfaces.IINIAware"
-    factory=".exportimport.INIAwareFileAdapter"
-    provides=".interfaces.IFilesystemImporter"
-    />
-
-  <adapter
-    for=".interfaces.IDAVAware"
-    factory=".exportimport.DAVAwareFileAdapter"
-    provides=".interfaces.IFilesystemExporter"
-    />
-
-  <adapter
-    for=".interfaces.IDAVAware"
-    factory=".exportimport.DAVAwareFileAdapter"
-    provides=".interfaces.IFilesystemImporter"
-    />
-
-</configure>

Deleted: CMF/trunk/CMFCore/nodeadapters.py
===================================================================
--- CMF/trunk/CMFCore/nodeadapters.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/CMFCore/nodeadapters.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,243 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""CMFCore node adapters.
-
-$Id$
-"""
-
-from Products.GenericSetup.interfaces import PURGE, UPDATE
-from Products.GenericSetup.utils import I18NURI
-from Products.GenericSetup.utils import NodeAdapterBase
-from Products.GenericSetup.utils import ObjectManagerHelpers
-from Products.GenericSetup.utils import PropertyManagerHelpers
-
-from interfaces import IAction
-from interfaces import IActionCategory
-from interfaces import IActionsTool
-from interfaces import ICookieCrumbler
-from interfaces.portal_actions import ActionProvider as IActionProvider
-from utils import getToolByName
-
-_SPECIAL_PROVIDERS = ('portal_actions', 'portal_types', 'portal_workflow')
-
-
-class ActionCategoryNodeAdapter(NodeAdapterBase, ObjectManagerHelpers,
-                                PropertyManagerHelpers):
-
-    """Node im- and exporter for ActionCategory.
-    """
-
-    __used_for__ = IActionCategory
-
-    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())
-        return node
-
-    def importNode(self, node, mode=PURGE):
-        """Import the object from the DOM node.
-        """
-        if mode == PURGE:
-            self._purgeProperties()
-            self._purgeObjects()
-
-        self._initProperties(node, mode)
-        self._initObjects(node, mode)
-
-
-class ActionNodeAdapter(NodeAdapterBase, PropertyManagerHelpers):
-
-    """Node im- and exporter for Action.
-    """
-
-    __used_for__ = IAction
-
-    def exportNode(self, doc):
-        """Export the object as a DOM node.
-        """
-        self._doc = doc
-        node = self._getObjectNode('object')
-        node.appendChild(self._extractProperties())
-        return node
-
-    def importNode(self, node, mode=PURGE):
-        """Import the object from the DOM node.
-        """
-        self._initProperties(node, mode)
-
-
-class ActionsToolNodeAdapter(NodeAdapterBase, ObjectManagerHelpers):
-
-    """Node im- and exporter for ActionsTool.
-    """
-
-    __used_for__ = IActionsTool
-
-    def exportNode(self, doc):
-        """Export the object as a DOM node.
-        """
-        self._doc = doc
-        node = self._getObjectNode('object')
-        node.setAttribute('xmlns:i18n', I18NURI)
-        node.appendChild(self._extractProviders())
-        node.appendChild(self._extractObjects())
-        return node
-
-    def importNode(self, node, mode=PURGE):
-        """Import the object from the DOM node.
-        """
-        if mode == PURGE:
-            self._purgeProviders()
-            self._purgeObjects()
-
-        self._initObjects(node, mode)
-        self._initProviders(node, mode)
-
-    def _extractProviders(self):
-        fragment = self._doc.createDocumentFragment()
-        for provider_id in self.context.listActionProviders():
-            child = self._doc.createElement('action-provider')
-            child.setAttribute('name', provider_id)
-            # BBB: for CMF 1.5 profiles
-            sub = self._extractOldstyleActions(provider_id)
-            child.appendChild(sub)
-            fragment.appendChild(child)
-        return fragment
-
-    def _extractOldstyleActions(self, provider_id):
-        # BBB: for CMF 1.5 profiles
-        fragment = self._doc.createDocumentFragment()
-
-        provider = getToolByName(self.context, provider_id)
-        if not IActionProvider.isImplementedBy(provider):
-            return fragment
-
-        if provider_id == 'portal_actions':
-            actions = provider._actions
-        else:
-            actions = provider.listActions()
-
-        if actions and isinstance(actions[0], dict):
-            return fragment
-
-        for ai in actions:
-            mapping = ai.getMapping()
-            child = self._doc.createElement('action')
-            child.setAttribute('action_id', mapping['id'])
-            child.setAttribute('category', mapping['category'])
-            child.setAttribute('condition_expr', mapping['condition'])
-            child.setAttribute('title', mapping['title'])
-            child.setAttribute('url_expr', mapping['action'])
-            child.setAttribute('visible', str(mapping['visible']))
-            for permission in mapping['permissions']:
-                sub = self._doc.createElement('permission')
-                sub.appendChild(self._doc.createTextNode(permission))
-                child.appendChild(sub)
-            fragment.appendChild(child)
-        return fragment
-
-    def _purgeProviders(self):
-        for provider_id in self.context.listActionProviders():
-            self.context.deleteActionProvider(provider_id)
-
-    def _initProviders(self, node, mode):
-        for child in node.childNodes:
-            if child.nodeName != 'action-provider':
-                continue
-
-            provider_id = str(child.getAttribute('name'))
-            if not provider_id:
-                # BBB: for CMF 1.5 profiles
-                provider_id = str(child.getAttribute('id'))
-            if child.hasAttribute('remove'):
-                if provider_id in self.context.listActionProviders():
-                    self.context.deleteActionProvider(provider_id)
-                continue
-
-            if provider_id in _SPECIAL_PROVIDERS and \
-                    provider_id not in self.context.listActionProviders():
-                self.context.addActionProvider(provider_id)
-
-            # BBB: for CMF 1.5 profiles
-            self._initOldstyleActions(child, mode)
-
-    def _initOldstyleActions(self, node, mode):
-        # BBB: for CMF 1.5 profiles
-        doc = node.ownerDocument
-        fragment = doc.createDocumentFragment()
-        for child in node.childNodes:
-            if child.nodeName != 'action':
-                continue
-
-            parent = fragment
-            for category_id in child.getAttribute('category').split('/'):
-                newnode = doc.createElement('object')
-                newnode.setAttribute('name', str(category_id))
-                newnode.setAttribute('meta_type', 'CMF Action Category')
-                parent.appendChild(newnode)
-                parent = newnode
-            newnode = doc.createElement('object')
-            newnode.setAttribute('name', str(child.getAttribute('action_id')))
-            newnode.setAttribute('meta_type', 'CMF Action')
-
-            mapping = {'title': 'title',
-                       'url_expr': 'url_expr',
-                       'condition_expr': 'available_expr',
-                       'visible': 'visible'}
-            for old, new in mapping.iteritems():
-                newchild = doc.createElement('property')
-                newchild.setAttribute('name', new)
-                newsub = doc.createTextNode(child.getAttribute(old))
-                newchild.appendChild(newsub)
-                newnode.appendChild(newchild)
-
-            newchild = doc.createElement('property')
-            newchild.setAttribute('name', 'permissions')
-            for sub in child.childNodes:
-                if sub.nodeName == 'permission':
-                    newsub = doc.createElement('element')
-                    newsub.setAttribute('value', self._getNodeText(sub))
-                    newchild.appendChild(newsub)
-            newnode.appendChild(newchild)
-
-            parent.appendChild(newnode)
-
-        self._initObjects(fragment, UPDATE)
-
-
-class CookieCrumblerNodeAdapter(NodeAdapterBase, PropertyManagerHelpers):
-
-    """Node im- and exporter for CookieCrumbler.
-    """
-
-    __used_for__ = ICookieCrumbler
-
-    def exportNode(self, doc):
-        """Export the object as a DOM node.
-        """
-        self._doc = doc
-        node = self._getObjectNode('object')
-        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)

Deleted: CMF/trunk/CMFCore/tests/conformance.py
===================================================================
--- CMF/trunk/CMFCore/tests/conformance.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/CMFCore/tests/conformance.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,46 +0,0 @@
-""" Mix-in classes for testing interface conformance.
-
-$Id$
-"""
-
-class ConformsToISimpleItem:
-
-    def test_conforms_to_Five_ISimpleItem(self):
-        from zope.interface.verify import verifyClass
-        from Products.Five.interfaces import ISimpleItem
-
-        verifyClass(ISimpleItem, self._getTargetClass())
-
-class ConformsToIINIAware:
-
-    def test_conforms_to_IINIAware(self):
-        from zope.interface.verify import verifyClass
-        from Products.CMFCore.interfaces import IINIAware
-
-        verifyClass(IINIAware, self._getTargetClass())
-
-class ConformsToICSVAware:
-
-    def test_conforms_to_ICSVAware(self):
-        from zope.interface.verify import verifyClass
-        from Products.CMFCore.interfaces import ICSVAware
-
-        verifyClass(ICSVAware, self._getTargetClass())
-
-class ConformsToIFilesystemExporter:
-    """ Mix-in for test cases whose target class implements IFilesystemExporter.
-    """
-    def test_conforms_to_IFilesystemExporter(self):
-        from zope.interface.verify import verifyClass
-        from Products.CMFCore.interfaces import IFilesystemExporter
-
-        verifyClass(IFilesystemExporter, self._getTargetClass())
-
-class ConformsToIFilesystemImporter:
-    """ Mix-in for test cases whose target class implements IFilesystemImporter.
-    """
-    def test_conforms_to_IFilesystemImporter(self):
-        from zope.interface.verify import verifyClass
-        from Products.CMFCore.interfaces import IFilesystemImporter
-
-        verifyClass(IFilesystemImporter, self._getTargetClass())

Deleted: CMF/trunk/CMFCore/tests/test_exportimport.py
===================================================================
--- CMF/trunk/CMFCore/tests/test_exportimport.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/CMFCore/tests/test_exportimport.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,870 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 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.
-#
-##############################################################################
-""" Unit tests for Products.CMFCore.exportimport
-
-$Id$
-"""
-
-import unittest
-import Testing
-
-from csv import reader
-from ConfigParser import ConfigParser
-from StringIO import StringIO
-
-from zope.app.tests.placelesssetup import PlacelessSetup
-
-from Products.GenericSetup.tests.common import DummyExportContext
-from Products.GenericSetup.tests.common import DummyImportContext
-
-from conformance import ConformsToIFilesystemExporter
-from conformance import ConformsToIFilesystemImporter
-
-class SiteStructureExporterTests(PlacelessSetup,
-                                 unittest.TestCase,
-                                ):
-
-    def _getExporter(self):
-        from Products.CMFCore.exportimport import exportSiteStructure
-        return exportSiteStructure
-
-    def _getImporter(self):
-        from Products.CMFCore.exportimport import importSiteStructure
-        return importSiteStructure
-
-    def _makeSetupTool(self):
-        from Products.GenericSetup.tool import SetupTool
-        return SetupTool('portal_setup')
-
-    def _setUpAdapters(self):
-        from zope.app.tests import ztapi
-        #from OFS.Image import File
-        from zope.interface import classImplements
-
-        from Products.CMFCore.interfaces import IFilesystemExporter
-        from Products.CMFCore.interfaces import IFilesystemImporter
-        from Products.CMFCore.interfaces import IFolderish
-        from Products.CMFCore.interfaces import ICSVAware
-        from Products.CMFCore.interfaces import IINIAware
-
-        from Products.CMFCore.exportimport import \
-             StructureFolderWalkingAdapter
-        from Products.CMFCore.exportimport import \
-             CSVAwareFileAdapter
-        from Products.CMFCore.exportimport import \
-             INIAwareFileAdapter
-        
-        #from Products.CMFCore.exportimport import \
-        #        OFSFileAdapter
-
-        ztapi.provideAdapter(IFolderish,
-                             IFilesystemExporter, 
-                             StructureFolderWalkingAdapter,
-                            )
-
-        ztapi.provideAdapter(IFolderish,
-                             IFilesystemImporter, 
-                             StructureFolderWalkingAdapter,
-                            )
-
-        ztapi.provideAdapter(ICSVAware,
-                             IFilesystemExporter, 
-                             CSVAwareFileAdapter,
-                            )
-
-        ztapi.provideAdapter(ICSVAware,
-                             IFilesystemImporter, 
-                             CSVAwareFileAdapter,
-                            )
-
-        ztapi.provideAdapter(IINIAware,
-                             IFilesystemExporter, 
-                             INIAwareFileAdapter,
-                            )
-
-        ztapi.provideAdapter(IINIAware,
-                             IFilesystemImporter, 
-                             INIAwareFileAdapter,
-                            )
-
-
-    def test_export_empty_site(self):
-        self._setUpAdapters()
-        site = _makeFolder('site', site_folder=True)
-        site.title = 'test_export_empty_site'
-        site.description = 'Testing export of an empty site.'
-        context = DummyExportContext(site)
-        exporter = self._getExporter()
-        exporter(context)
-
-        self.assertEqual(len(context._wrote), 2)
-        filename, text, content_type = context._wrote[0]
-        self.assertEqual(filename, 'structure/.objects')
-        self.assertEqual(content_type, 'text/comma-separated-values')
-
-        objects = [x for x in reader(StringIO(text))]
-        self.assertEqual(len(objects), 0)
-
-        filename, text, content_type = context._wrote[1]
-        self.assertEqual(filename, 'structure/.properties')
-        self.assertEqual(content_type, 'text/plain')
-
-        parser = ConfigParser()
-        parser.readfp(StringIO(text))
-
-        self.assertEqual(parser.get('DEFAULT', 'Title'),
-                         site.title)
-        self.assertEqual(parser.get('DEFAULT', 'Description'),
-                         site.description)
-
-    def test_export_empty_site_with_setup_tool(self):
-        self._setUpAdapters()
-        site = _makeFolder('site', site_folder=True)
-        site._setObject('setup_tool', self._makeSetupTool())
-        site.title = 'test_export_empty_site_with_setup_tool'
-        site.description = 'Testing export of an empty site with setup tool.'
-        context = DummyExportContext(site)
-        exporter = self._getExporter()
-        exporter(context)
-
-        self.assertEqual(len(context._wrote), 2)
-        filename, text, content_type = context._wrote[0]
-        self.assertEqual(filename, 'structure/.objects')
-        self.assertEqual(content_type, 'text/comma-separated-values')
-
-        objects = [x for x in reader(StringIO(text))]
-        self.assertEqual(len(objects), 0)
-
-        filename, text, content_type = context._wrote[1]
-        self.assertEqual(filename, 'structure/.properties')
-        self.assertEqual(content_type, 'text/plain')
-
-        parser = ConfigParser()
-        parser.readfp(StringIO(text))
-
-        self.assertEqual(parser.get('DEFAULT', 'Title'),
-                         site.title)
-        self.assertEqual(parser.get('DEFAULT', 'Description'),
-                         site.description)
-
-    def test_export_site_with_non_exportable_simple_items(self):
-        self._setUpAdapters()
-        ITEM_IDS = ('foo', 'bar', 'baz')
-
-        site = _makeFolder('site', site_folder=True)
-        site.title = 'AAA'
-        site.description = 'BBB'
-        for id in ITEM_IDS:
-            site._setObject(id, _makeItem(id))
-
-        context = DummyExportContext(site)
-        exporter = self._getExporter()
-        exporter(context)
-
-        self.assertEqual(len(context._wrote), 2)
-        filename, text, content_type = context._wrote[0]
-        self.assertEqual(filename, 'structure/.objects')
-        self.assertEqual(content_type, 'text/comma-separated-values')
-
-        objects = [x for x in reader(StringIO(text))]
-        self.assertEqual(len(objects), 3)
-        for index in range(len(ITEM_IDS)):
-            self.assertEqual(objects[index][0], ITEM_IDS[index])
-            self.assertEqual(objects[index][1], TEST_CONTENT)
-
-        filename, text, content_type = context._wrote[1]
-        self.assertEqual(filename, 'structure/.properties')
-        self.assertEqual(content_type, 'text/plain')
-        parser = ConfigParser()
-        parser.readfp(StringIO(text))
-
-        self.assertEqual(parser.get('DEFAULT', 'title'), 'AAA')
-        self.assertEqual(parser.get('DEFAULT', 'description'), 'BBB')
-
-    def test_export_site_with_exportable_simple_items(self):
-        self._setUpAdapters()
-        ITEM_IDS = ('foo', 'bar', 'baz')
-
-        site = _makeFolder('site', site_folder=True)
-        site.title = 'AAA'
-        site.description = 'BBB'
-        for id in ITEM_IDS:
-            site._setObject(id, _makeINIAware(id))
-
-        context = DummyExportContext(site)
-        exporter = self._getExporter()
-        exporter(context)
-
-        self.assertEqual(len(context._wrote), 2 + len(ITEM_IDS))
-        filename, text, content_type = context._wrote[0]
-        self.assertEqual(filename, 'structure/.objects')
-        self.assertEqual(content_type, 'text/comma-separated-values')
-
-        objects = [x for x in reader(StringIO(text))]
-        self.assertEqual(len(objects), 3)
-        for index in range(len(ITEM_IDS)):
-            self.assertEqual(objects[index][0], ITEM_IDS[index])
-            self.assertEqual(objects[index][1], TEST_INI_AWARE)
-
-            filename, text, content_type = context._wrote[index+2]
-            self.assertEqual(filename, 'structure/%s.ini' % ITEM_IDS[index])
-            object = site._getOb(ITEM_IDS[index])
-            self.assertEqual(text.strip(),
-                             object.as_ini().strip())
-            self.assertEqual(content_type, 'text/plain')
-
-        filename, text, content_type = context._wrote[1]
-        self.assertEqual(filename, 'structure/.properties')
-        self.assertEqual(content_type, 'text/plain')
-        parser = ConfigParser()
-        parser.readfp(StringIO(text))
-
-        self.assertEqual(parser.get('DEFAULT', 'title'), 'AAA')
-        self.assertEqual(parser.get('DEFAULT', 'description'), 'BBB')
-
-    def test_export_site_with_subfolders(self):
-        self._setUpAdapters()
-        FOLDER_IDS = ('foo', 'bar', 'baz')
-
-        site = _makeFolder('site', site_folder=True)
-        site.title = 'AAA'
-        site.description = 'BBB'
-        for id in FOLDER_IDS:
-            folder = _makeFolder(id)
-            folder.title = 'Title: %s' % id
-            folder.description = 'xyzzy'
-            site._setObject(id, folder)
-
-        context = DummyExportContext(site)
-        exporter = self._getExporter()
-        exporter(context)
-
-        self.assertEqual(len(context._wrote), 2 + (2 *len(FOLDER_IDS)))
-        filename, text, content_type = context._wrote[0]
-        self.assertEqual(filename, 'structure/.objects')
-        self.assertEqual(content_type, 'text/comma-separated-values')
-
-        objects = [x for x in reader(StringIO(text))]
-        self.assertEqual(len(objects), 3)
-
-        for index in range(len(FOLDER_IDS)):
-            id = FOLDER_IDS[index]
-            self.assertEqual(objects[index][0], id)
-            self.assertEqual(objects[index][1], TEST_FOLDER)
-
-            filename, text, content_type = context._wrote[2 + (2 * index)]
-            self.assertEqual(filename, '/'.join(('structure', id, '.objects')))
-            self.assertEqual(content_type, 'text/comma-separated-values')
-            subobjects = [x for x in reader(StringIO(text))]
-            self.assertEqual(len(subobjects), 0)
-
-            filename, text, content_type = context._wrote[2 + (2 * index) + 1]
-            self.assertEqual(filename,
-                             '/'.join(('structure', id, '.properties')))
-            self.assertEqual(content_type, 'text/plain')
-            parser = ConfigParser()
-            parser.readfp(StringIO(text))
-
-            self.assertEqual(parser.get('DEFAULT', 'Title'), 'Title: %s' % id)
-
-        filename, text, content_type = context._wrote[1]
-        self.assertEqual(filename, 'structure/.properties')
-        self.assertEqual(content_type, 'text/plain')
-
-        parser = ConfigParser()
-        parser.readfp(StringIO(text))
-
-        self.assertEqual(parser.get('DEFAULT', 'title'), 'AAA')
-        self.assertEqual(parser.get('DEFAULT', 'description'), 'BBB')
-
-    def test_export_site_with_csvaware(self):
-        self._setUpAdapters()
-
-        site = _makeFolder('site', site_folder=True)
-        site.title = 'test_export_site_with_csvaware'
-        site.description = 'Testing export of an site with CSV-aware content.'
-
-        site._setObject('aware', _makeCSVAware('aware'))
-
-        context = DummyExportContext(site)
-        exporter = self._getExporter()
-        exporter(context)
-
-        self.assertEqual(len(context._wrote), 3)
-        filename, text, content_type = context._wrote[0]
-        self.assertEqual(filename, 'structure/.objects')
-        self.assertEqual(content_type, 'text/comma-separated-values')
-
-        objects = [x for x in reader(StringIO(text))]
-        self.assertEqual(len(objects), 1)
-        self.assertEqual(objects[0][0], 'aware')
-        self.assertEqual(objects[0][1], TEST_CSV_AWARE)
-
-        filename, text, content_type = context._wrote[1]
-        self.assertEqual(filename, 'structure/.properties')
-        self.assertEqual(content_type, 'text/plain')
-
-        parser = ConfigParser()
-        parser.readfp(StringIO(text))
-
-        self.assertEqual(parser.get('DEFAULT', 'Title'),
-                                    site.title)
-        self.assertEqual(parser.get('DEFAULT', 'Description'),
-                                    site.description)
-
-        filename, text, content_type = context._wrote[2]
-        self.assertEqual(filename, 'structure/aware.csv')
-        self.assertEqual(content_type, 'text/comma-separated-values')
-        rows = [x for x in reader(StringIO(text))]
-        self.assertEqual(len(rows), 2)
-        self.assertEqual(rows[0][0], 'one')
-        self.assertEqual(rows[0][1], 'two')
-        self.assertEqual(rows[0][2], 'three')
-        self.assertEqual(rows[1][0], 'four')
-        self.assertEqual(rows[1][1], 'five')
-        self.assertEqual(rows[1][2], 'six')
-
-    def test_import_empty_site(self):
-        self._setUpAdapters()
-        site = _makeFolder('site', site_folder=True)
-        context = DummyImportContext(site)
-        context._files['structure/.objects'] = ''
-        importer = self._getImporter()
-        self.assertEqual(len(site.objectIds()), 0)
-        importer(context)
-        self.assertEqual(len(site.objectIds()), 0)
-
-    def test_import_empty_site_with_setup_tool(self):
-        self._setUpAdapters()
-        site = _makeFolder('site', site_folder=True)
-        site._setObject('setup_tool', self._makeSetupTool())
-        context = DummyImportContext(site)
-        importer = self._getImporter()
-
-        self.assertEqual(len(site.objectIds()), 1)
-        self.assertEqual(site.objectIds()[0], 'setup_tool')
-        importer(context)
-        self.assertEqual(len(site.objectIds()), 1)
-        self.assertEqual(site.objectIds()[0], 'setup_tool')
-
-    def test_import_site_with_subfolders(self):
-        self._setUpAdapters()
-        FOLDER_IDS = ('foo', 'bar', 'baz')
-
-        site = _makeFolder('site', site_folder=True)
-
-        context = DummyImportContext(site)
-
-        for id in FOLDER_IDS:
-            context._files['structure/%s/.objects' % id] = ''
-            context._files['structure/%s/.properties' % id] = (
-                _PROPERTIES_TEMPLATE % id )
-
-        _ROOT_OBJECTS = '\n'.join(['%s,%s' % (id, TEST_FOLDER)
-                                        for id in FOLDER_IDS])
-
-        context._files['structure/.objects'] = _ROOT_OBJECTS
-        context._files['structure/.properties'] = (
-                _PROPERTIES_TEMPLATE % 'Test Site')
-
-        importer = self._getImporter()
-        importer(context)
-
-        content = site.contentValues()
-        self.assertEqual(len(content), len(FOLDER_IDS))
-
-    def test_import_site_with_subitems(self):
-        self._setUpAdapters()
-        ITEM_IDS = ('foo', 'bar', 'baz')
-
-        site = _makeFolder('site', site_folder=True)
-
-        context = DummyImportContext(site)
-        # We want to add 'baz' to 'foo', without losing 'bar'
-        context._files['structure/.objects'] = '\n'.join(
-                            ['%s,%s' % (x, TEST_INI_AWARE) for x in ITEM_IDS])
-        for index in range(len(ITEM_IDS)):
-            id = ITEM_IDS[index]
-            context._files[
-                    'structure/%s.ini' % id] = KNOWN_INI % ('Title: %s' % id,
-                                                            'xyzzy',
-                                                           )
-        importer = self._getImporter()
-        importer(context)
-
-        after = site.objectIds()
-        self.assertEqual(len(after), len(ITEM_IDS))
-        for found_id, expected_id in zip(after, ITEM_IDS):
-            self.assertEqual(found_id, expected_id)
-
-    def test_import_site_with_subitem_unknown_portal_type(self):
-        self._setUpAdapters()
-        ITEM_IDS = ('foo', 'bar', 'baz')
-
-        site = _makeFolder('site', site_folder=True)
-
-        context = DummyImportContext(site)
-        # We want to add 'baz' to 'foo', without losing 'bar'
-        context._files['structure/.objects'] = '\n'.join(
-                                ['%s,Unknown Type' % x for x in ITEM_IDS])
-        for index in range(len(ITEM_IDS)):
-            id = ITEM_IDS[index]
-            context._files[
-                    'structure/%s.ini' % id] = KNOWN_INI % ('Title: %s' % id,
-                                                            'xyzzy',
-                                                           )
-
-        importer = self._getImporter()
-        importer(context)
-
-        after = site.objectIds()
-        self.assertEqual(len(after), 0)
-        self.assertEqual(len(context._notes), len(ITEM_IDS))
-        for component, message in context._notes:
-            self.assertEqual(component, 'SFWA')
-            self.failUnless(message.startswith("Couldn't make"))
-
-    def test_import_site_with_subitems_and_no_preserve(self):
-        self._setUpAdapters()
-        ITEM_IDS = ('foo', 'bar', 'baz')
-
-        site = _makeFolder('site', site_folder=True)
-        for id in ITEM_IDS:
-            site._setObject(id, _makeItem(id))
-
-        context = DummyImportContext(site)
-        # We want to add 'baz' to 'foo', without losing 'bar'
-        context._files['structure/.objects'] = ''
-
-        importer = self._getImporter()
-        importer(context)
-
-        self.assertEqual(len(site.objectIds()), 0)
-
-    def test_import_site_with_subitemss_and_preserve(self):
-        self._setUpAdapters()
-        ITEM_IDS = ('foo', 'bar', 'baz')
-
-        site = _makeFolder('site', site_folder=True)
-        for id in ITEM_IDS:
-            site._setObject(id, _makeItem(id))
-
-        context = DummyImportContext(site)
-        # We want to add 'baz' to 'foo', without losing 'bar'
-        context._files['structure/.objects'] = ''
-        context._files['structure/.preserve'] = '*'
-
-        importer = self._getImporter()
-        importer(context)
-
-        after = site.objectIds()
-        self.assertEqual(len(after), len(ITEM_IDS))
-        for i in range(len(ITEM_IDS)):
-            self.assertEqual(after[i], ITEM_IDS[i])
-
-    def test_import_site_with_subitemss_and_preserve_partial(self):
-        self._setUpAdapters()
-        ITEM_IDS = ('foo', 'bar', 'baz')
-
-        site = _makeFolder('site', site_folder=True)
-        for id in ITEM_IDS:
-            site._setObject(id, _makeItem(id))
-
-        context = DummyImportContext(site)
-        # We want to add 'baz' to 'foo', without losing 'bar'
-        context._files['structure/.objects'] = ''
-        context._files['structure/.preserve'] = 'b*'
-
-        importer = self._getImporter()
-        importer(context)
-
-        after = site.objectIds()
-        self.assertEqual(len(after), 2)
-        self.assertEqual(after[0], 'bar')
-        self.assertEqual(after[1], 'baz')
-
-    def test_import_site_with_subfolders_and_preserve(self):
-        self._setUpAdapters()
-
-        site = _makeFolder('site', site_folder=True)
-        site._setObject('foo', _makeFolder('foo'))
-        site.foo._setObject('bar', _makeFolder('bar'))
-
-        context = DummyImportContext(site)
-        # We want to add 'baz' to 'foo', without losing 'bar'
-        context._files['structure/.objects'] = 'foo,%s' % TEST_FOLDER
-        context._files['structure/.preserve'] = '*'
-        context._files['structure/foo/.objects'] = 'baz,%s' % TEST_FOLDER
-        context._files['structure/foo/.preserve'] = '*'
-        context._files['structure/foo/baz/.objects'] = ''
-
-        importer = self._getImporter()
-        importer(context)
-
-        self.assertEqual(len(site.objectIds()), 1)
-        self.assertEqual(site.objectIds()[0], 'foo')
-
-        self.assertEqual(len(site.foo.objectIds()), 2, site.foo.objectIds())
-        self.assertEqual(site.foo.objectIds()[0], 'bar')
-        self.assertEqual(site.foo.objectIds()[1], 'baz')
-
-
-class Test_globpattern(unittest.TestCase):
-
-    NAMELIST = ('foo', 'bar', 'baz', 'bam', 'qux', 'quxx', 'quxxx')
-
-    def _checkResults(self, globpattern, namelist, expected):
-        from Products.CMFCore.exportimport import _globtest
-        found = _globtest(globpattern, namelist)
-        self.assertEqual(len(found), len(expected))
-        for found_item, expected_item in zip(found, expected):
-            self.assertEqual(found_item, expected_item)
-
-    def test_star(self):
-        self._checkResults('*', self.NAMELIST, self.NAMELIST)
-
-    def test_simple(self):
-        self._checkResults('b*', self.NAMELIST,
-                            [x for x in self.NAMELIST if x.startswith('b')])
-
-    def test_multiple(self):
-        self._checkResults('b*\n*x', self.NAMELIST,
-                            [x for x in self.NAMELIST
-                                if x.startswith('b') or x.endswith('x')])
-
-
-class CSVAwareFileAdapterTests(unittest.TestCase,
-                               ConformsToIFilesystemExporter,
-                               ConformsToIFilesystemImporter,
-                              ):
-
-    def _getTargetClass(self):
-        from Products.CMFCore.exportimport import CSVAwareFileAdapter
-        return CSVAwareFileAdapter
-
-    def _makeOne(self, context, *args, **kw):
-        return self._getTargetClass()(context, *args, **kw)
-
-    def _makeCSVAware(self, sheet_id, csv=''):
-        class Foo:
-            def getId(self):
-                return self._id
-            def as_csv(self):
-                return self.csv
-            def put_csv(self, stream):
-                self.new_csv = stream.getvalue()
-
-        foo = Foo()
-        foo._id = sheet_id
-        foo.csv = csv
-        foo.new_csv = None
-
-        return foo
-
-
-    def test_export_with_known_CSV(self):
-        KNOWN_CSV = """\
-one,two,three
-four,five,six
-"""
-        sheet = self._makeCSVAware('config', KNOWN_CSV)
-
-        adapter = self._makeOne(sheet)
-        context = DummyExportContext(None)
-        adapter.export(context, 'subpath/to/sheet')
-
-        self.assertEqual(len(context._wrote), 1)
-        filename, text, content_type = context._wrote[0]
-        self.assertEqual(filename, 'subpath/to/sheet/config.csv')
-        self.assertEqual(content_type, 'text/comma-separated-values')
-
-        self.assertEqual(text.strip(), KNOWN_CSV.strip())
-
-    def test_import_with_known_CSV(self):
-        ORIG_CSV = """\
-one,two,three
-four,five,six
-"""
-        NEW_CSV = """\
-four,five,six
-one,two,three
-"""
-        sheet = self._makeCSVAware('config', ORIG_CSV)
-
-        adapter = self._makeOne(sheet)
-        context = DummyImportContext(None)
-        context._files['subpath/to/sheet/config.csv'] = NEW_CSV
-        adapter.import_(context, 'subpath/to/sheet')
-
-        self.assertEqual(sheet.new_csv.strip(), NEW_CSV.strip())
-
-
-_PROPERTIES_TEMPLATE = """
-[DEFAULT]
-Title = %s
-Description = This is a test
-"""
-
-class INIAwareFileAdapterTests(unittest.TestCase,
-                               ConformsToIFilesystemExporter,
-                               ConformsToIFilesystemImporter,
-                               ):
-
-    def _getTargetClass(self):
-        from Products.CMFCore.exportimport import INIAwareFileAdapter
-        return INIAwareFileAdapter
-
-    def _makeOne(self, context, *args, **kw):
-        return self._getTargetClass()(context, *args, **kw)
-
-    def test_export_ini_file(self):
-        ini_file = _makeINIAware('ini_file.html')
-        adapter = self._makeOne(ini_file)
-        context = DummyExportContext(None)
-        adapter.export(context, 'subpath/to')
-
-        self.assertEqual(len(context._wrote), 1)
-        filename, text, content_type = context._wrote[0]
-        self.assertEqual(filename, 'subpath/to/ini_file.html.ini')
-        self.assertEqual(content_type, 'text/plain')
-
-        self.assertEqual(text.strip(), ini_file.as_ini().strip())
-
-    def test_import_ini_file(self):
-        ini_file = _makeINIAware('ini_file.html')
-        adapter = self._makeOne(ini_file)
-        context = DummyImportContext(None)
-        context._files['subpath/to/ini_file.html.ini'] = (
-                        KNOWN_INI % ('Title: ini_file', 'abc'))
-
-        adapter.import_(context, 'subpath/to')
-        text = ini_file._was_put
-        parser = ConfigParser()
-        parser.readfp(StringIO(text))
-        self.assertEqual(parser.get('DEFAULT', 'title'), 'Title: ini_file')
-        self.assertEqual(parser.get('DEFAULT', 'description'), 'abc')
-
-
-class DAVAwareFileAdapterTests(unittest.TestCase,
-                               ConformsToIFilesystemExporter,
-                               ConformsToIFilesystemImporter,
-                               ):
-
-    def _getTargetClass(self):
-        from Products.CMFCore.exportimport import DAVAwareFileAdapter
-        return DAVAwareFileAdapter
-
-    def _makeOne(self, context, *args, **kw):
-        return self._getTargetClass()(context, *args, **kw)
-
-    def test_export_dav_file(self):
-        dav_file = _makeDAVAware('dav_file.html')
-        adapter = self._makeOne(dav_file)
-        context = DummyExportContext(None)
-        adapter.export(context, 'subpath/to')
-
-        self.assertEqual(len(context._wrote), 1)
-        filename, text, content_type = context._wrote[0]
-        self.assertEqual(filename, 'subpath/to/dav_file.html')
-        self.assertEqual(content_type, 'text/plain')
-        self.assertEqual(text.strip(), dav_file.manage_FTPget().strip())
-
-    def test_import_dav_file(self):
-        VALUES = ('Title: dav_file', 'Description: abc', 'body goes here')
-        dav_file = _makeDAVAware('dav_file.html')
-        adapter = self._makeOne(dav_file)
-        context = DummyImportContext(None)
-        context._files['subpath/to/dav_file.html'] = KNOWN_DAV % VALUES
-
-        adapter.import_(context, 'subpath/to')
-        text = dav_file._was_put == KNOWN_DAV % VALUES
-
-
-TEST_CSV_AWARE = 'Test CSV Aware'
-KNOWN_CSV = """\
-one,two,three
-four,five,six
-"""
-
-def _makeCSVAware(id):
-    from OFS.SimpleItem import SimpleItem
-    from zope.interface import implements
-    from Products.CMFCore.interfaces import IDynamicType
-    from Products.CMFCore.interfaces import ICSVAware
-
-    class _TestCSVAware(SimpleItem):
-        implements(IDynamicType, ICSVAware)
-        _was_put = None
-        portal_type = TEST_CSV_AWARE
-
-        def getPortalTypeName(self):
-            return self.portal_type
-
-        def as_csv(self):
-            return KNOWN_CSV
-
-        def put_csv(self, text):
-            self._was_put = text
-
-    aware = _TestCSVAware()
-    aware._setId(id)
-
-    return aware
-
-
-TEST_INI_AWARE = 'Test INI Aware'
-KNOWN_INI = """\
-[DEFAULT]
-title = %s
-description = %s
-"""
-
-def _makeINIAware(id):
-    from OFS.SimpleItem import SimpleItem
-    from zope.interface import implements
-    from Products.CMFCore.interfaces import IDynamicType
-    from Products.CMFCore.interfaces import IINIAware
-
-    class _TestINIAware(SimpleItem):
-        implements(IDynamicType, IINIAware)
-        _was_put = None
-        title = 'INI title'
-        description = 'INI description'
-        portal_type = TEST_INI_AWARE
-
-        def getPortalTypeName(self):
-            return self.portal_type
-
-        def as_ini(self):
-            return KNOWN_INI % (self.title, self.description)
-
-        def put_ini(self, text):
-            self._was_put = text
-
-    aware = _TestINIAware()
-    aware._setId(id)
-
-    return aware
-
-
-TEST_DAV_AWARE = 'Test DAV Aware'
-KNOWN_DAV = """\
-Title: %s
-Description: %s
-
-%s
-"""
-
-def _makeDAVAware(id):
-    from OFS.SimpleItem import SimpleItem
-    from zope.interface import implements
-    from Products.CMFCore.interfaces import IDynamicType
-    from Products.CMFCore.interfaces import IDAVAware
-
-    class _TestDAVAware(SimpleItem):
-        implements(IDynamicType, IDAVAware)
-        _was_put = None
-        title = 'DAV title'
-        description = 'DAV description'
-        body = 'DAV body'
-        portal_type = TEST_DAV_AWARE
-
-        def getPortalTypeName(self):
-            return self.portal_type
-
-        def manage_FTPget(self):
-            return KNOWN_DAV % (self.title, self.description, self.body)
-
-        def PUT(self, REQUEST, RESPONSE):
-            self._was_put = REQUEST.get('BODY', '')
-
-    aware = _TestDAVAware()
-    aware._setId(id)
-
-    return aware
-
-
-TEST_CONTENT = 'Test Content'
-
-def _makeItem(self):
-    from OFS.SimpleItem import SimpleItem
-    from zope.interface import implements
-    from Products.CMFCore.interfaces import IDynamicType
-
-    class _TestContent(SimpleItem):
-        implements(IDynamicType)
-        portal_type = TEST_CONTENT
-
-        def getPortalTypeName(self):
-            return self.portal_type
-
-    aware = _TestContent()
-    aware._setId(id)
-
-    return aware
-
-
-TEST_FOLDER = 'Test Folder'
-
-def _makeFolder(id, site_folder=False):
-    from zope.interface import directlyProvides
-    from zope.interface import providedBy
-    from Products.CMFCore.PortalFolder import PortalFolder
-    from Products.CMFCore.interfaces import ISiteRoot
-    from Products.CMFCore.TypesTool import TypesTool
-    from Products.CMFCore.tests.base.dummy import DummyType
-
-    class _TypeInfo(DummyType):
-        def _getId(self):
-            return self._id
-        def constructInstance(self, container, id, *args, **kw):
-            portal_type = self._getId()
-            if portal_type == TEST_FOLDER:
-                content = PortalFolder(id)
-            elif portal_type == TEST_CONTENT:
-                content = _makeItem()
-                content._setId(id)
-            elif portal_type == TEST_INI_AWARE:
-                content = _makeINIAware(id)
-            elif portal_type == TEST_CSV_AWARE:
-                content = _makeCSVAware(id)
-            else:
-                raise ValueError, 'Ugh'
-            content.portal_type = portal_type
-            container._setObject(id, content)
-            return container._getOb(id)
-
-    folder = PortalFolder(id)
-    folder.portal_type = TEST_FOLDER
-    if site_folder:
-        directlyProvides(folder, ISiteRoot + providedBy(folder))
-        tool = folder.portal_types = TypesTool()
-        tool._setObject(TEST_CSV_AWARE, _TypeInfo(TEST_CSV_AWARE))
-        tool._setObject(TEST_INI_AWARE, _TypeInfo(TEST_INI_AWARE))
-        tool._setObject(TEST_CONTENT, _TypeInfo(TEST_CONTENT))
-        tool._setObject(TEST_FOLDER, _TypeInfo(TEST_FOLDER))
-
-    return folder
-
-
-def test_suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(SiteStructureExporterTests))
-    suite.addTest(unittest.makeSuite(Test_globpattern))
-    suite.addTest(unittest.makeSuite(CSVAwareFileAdapterTests))
-    suite.addTest(unittest.makeSuite(INIAwareFileAdapterTests))
-    suite.addTest(unittest.makeSuite(DAVAwareFileAdapterTests))
-    return suite
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')

Deleted: CMF/trunk/CMFCore/tests/test_nodeadapters.py
===================================================================
--- CMF/trunk/CMFCore/tests/test_nodeadapters.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/CMFCore/tests/test_nodeadapters.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,195 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""CMFCore node adapter unit tests.
-
-$Id$
-"""
-
-import unittest
-import Testing
-import Zope2
-Zope2.startup()
-
-import Products
-from Products.Five import zcml
-from zope.app.tests.placelesssetup import PlacelessSetup
-
-from Products.CMFCore.tests.base.dummy import DummySite
-from Products.GenericSetup.testing import NodeAdapterTestCase
-
-
-_ACTION_XML = """\
-<object name="foo_action" meta_type="CMF Action">
- <property name="title">Foo</property>
- <property name="description"></property>
- <property name="url_expr">string:${object_url}/foo</property>
- <property name="icon_expr"></property>
- <property name="available_expr">python:1</property>
- <property name="permissions"/>
- <property name="visible">True</property>
-</object>
-"""
-
-_ACTIONCATEGORY_XML = """\
-<object name="foo_category" meta_type="CMF Action Category">
- <property name="title"></property>
- <object name="foo_action" meta_type="CMF Action">
-  <property name="title"></property>
-  <property name="description"></property>
-  <property name="url_expr"></property>
-  <property name="icon_expr"></property>
-  <property name="available_expr"></property>
-  <property name="permissions"/>
-  <property name="visible">True</property>
- </object>
-</object>
-"""
-
-_ACTIONSTOOL_XML = """\
-<object name="portal_actions" meta_type="CMF Actions Tool"
-   xmlns:i18n="http://xml.zope.org/namespaces/i18n">
- <action-provider name="portal_actions"/>
- <object name="foo_category" meta_type="CMF Action Category">
-  <property name="title"></property>
-  <object name="foo_action" meta_type="CMF Action" i18n:domain="foo_domain">
-   <property name="title" i18n:translate=""></property>
-   <property name="description" i18n:translate=""></property>
-   <property name="url_expr"></property>
-   <property name="icon_expr"></property>
-   <property name="available_expr"></property>
-   <property name="permissions"/>
-   <property name="visible">True</property>
-  </object>
- </object>
-</object>
-"""
-
-_COOKIECRUMBLER_XML = """\
-<object name="foo_cookiecrumbler" meta_type="Cookie Crumbler">
- <property name="auth_cookie">__ac</property>
- <property name="name_cookie">__ac_name</property>
- <property name="pw_cookie">__ac_password</property>
- <property name="persist_cookie">__ac_persistent</property>
- <property name="auto_login_page">login_form</property>
- <property name="logout_page">logged_out</property>
- <property name="unauth_page"></property>
- <property name="local_cookie_path">False</property>
- <property name="cache_header_value">private</property>
- <property name="log_username">True</property>
-</object>
-"""
-
-
-class ActionNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.CMFCore.nodeadapters import ActionNodeAdapter
-
-        return ActionNodeAdapter
-
-    def _populate(self, obj):
-        obj._setPropValue('title', 'Foo')
-        obj._setPropValue('url_expr', 'string:${object_url}/foo')
-        obj._setPropValue('available_expr', 'python:1')
-
-    def setUp(self):
-        from Products.CMFCore.ActionInformation import Action
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml', Products.CMFCore)
-
-        self._obj = Action('foo_action')
-        self._XML = _ACTION_XML
-
-
-class ActionCategoryNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.CMFCore.nodeadapters import ActionCategoryNodeAdapter
-
-        return ActionCategoryNodeAdapter
-
-    def _populate(self, obj):
-        from Products.CMFCore.ActionInformation import Action
-
-        obj._setObject('foo_action', Action('foo_action'))
-
-    def setUp(self):
-        from Products.CMFCore.ActionInformation import ActionCategory
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml', Products.CMFCore)
-
-        self._obj = ActionCategory('foo_category')
-        self._XML = _ACTIONCATEGORY_XML
-
-
-class ActionsToolNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.CMFCore.nodeadapters import ActionsToolNodeAdapter
-
-        return ActionsToolNodeAdapter
-
-    def _populate(self, obj):
-        from Products.CMFCore.ActionInformation import Action
-        from Products.CMFCore.ActionInformation import ActionCategory
-
-        obj._setObject('foo_category', ActionCategory('foo_category'))
-        obj.action_providers = ('portal_actions',)
-        obj.foo_category._setObject('foo_action', Action('foo_action'))
-        obj.foo_category.foo_action.i18n_domain = 'foo_domain'
-
-    def setUp(self):
-        from Products.CMFCore.ActionsTool import ActionsTool
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml', Products.CMFCore)
-
-        site = DummySite('site')
-        site._setObject('portal_actions', ActionsTool('portal_actions'))
-        self._obj = site.portal_actions
-        self._XML = _ACTIONSTOOL_XML
-
-
-class CookieCrumblerNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.CMFCore.nodeadapters import CookieCrumblerNodeAdapter
-
-        return CookieCrumblerNodeAdapter
-
-    def setUp(self):
-        from Products.CMFCore.CookieCrumbler import CookieCrumbler
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml', Products.CMFCore)
-
-        self._obj = CookieCrumbler('foo_cookiecrumbler')
-        self._XML = _COOKIECRUMBLER_XML
-
-
-def test_suite():
-    return unittest.TestSuite((
-        unittest.makeSuite(ActionNodeAdapterTests),
-        unittest.makeSuite(ActionCategoryNodeAdapterTests),
-        unittest.makeSuite(ActionsToolNodeAdapterTests),
-        unittest.makeSuite(CookieCrumblerNodeAdapterTests),
-        ))
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')


Property changes on: CMF/trunk/CMFDefault/exportimport.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Deleted: CMF/trunk/GenericSetup/MailHost/adapters.py
===================================================================
--- CMF/trunk/GenericSetup/MailHost/adapters.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/MailHost/adapters.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,48 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""MailHost node adapters.
-
-$Id$
-"""
-
-from Products.GenericSetup.interfaces import PURGE
-from Products.GenericSetup.utils import NodeAdapterBase
-
-from Products.MailHost.interfaces import IMailHost
-
-
-class MailHostNodeAdapter(NodeAdapterBase):
-
-    """Node im- and exporter for MailHost.
-    """
-
-    __used_for__ = IMailHost
-
-    def exportNode(self, doc):
-        """Export the object as a DOM node.
-        """
-        self._doc = doc
-        node = self._getObjectNode('object')
-        node.setAttribute('smtp_host', str(self.context.smtp_host))
-        node.setAttribute('smtp_port', str(self.context.smtp_port))
-        node.setAttribute('smtp_uid', self.context.smtp_uid)
-        node.setAttribute('smtp_pwd', self.context.smtp_pwd)
-        return node
-
-    def importNode(self, node, mode=PURGE):
-        """Import the object from the DOM node.
-        """
-        self.context.smtp_host = str(node.getAttribute('smtp_host'))
-        self.context.smtp_port = int(node.getAttribute('smtp_port'))
-        self.context.smtp_uid = node.getAttribute('smtp_uid')
-        self.context.smtp_pwd = node.getAttribute('smtp_pwd')

Modified: CMF/trunk/GenericSetup/MailHost/configure.zcml
===================================================================
--- CMF/trunk/GenericSetup/MailHost/configure.zcml	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/MailHost/configure.zcml	2005-10-17 18:48:24 UTC (rev 39493)
@@ -3,13 +3,13 @@
     >
 
   <adapter
-      factory=".adapters.MailHostNodeAdapter"
+      factory=".exportimport.MailHostNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.MailHost.interfaces.IMailHost"
       />
 
   <adapter
-      factory=".adapters.MailHostNodeAdapter"
+      factory=".exportimport.MailHostNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeImporter"
       for="Products.MailHost.interfaces.IMailHost"
       />

Copied: CMF/trunk/GenericSetup/MailHost/exportimport.py (from rev 39486, CMF/trunk/GenericSetup/MailHost/adapters.py)
===================================================================
--- CMF/trunk/GenericSetup/MailHost/adapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/GenericSetup/MailHost/exportimport.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,48 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""MailHost export / import support.
+
+$Id$
+"""
+
+from Products.GenericSetup.interfaces import PURGE
+from Products.GenericSetup.utils import NodeAdapterBase
+
+from Products.MailHost.interfaces import IMailHost
+
+
+class MailHostNodeAdapter(NodeAdapterBase):
+
+    """Node im- and exporter for MailHost.
+    """
+
+    __used_for__ = IMailHost
+
+    def exportNode(self, doc):
+        """Export the object as a DOM node.
+        """
+        self._doc = doc
+        node = self._getObjectNode('object')
+        node.setAttribute('smtp_host', str(self.context.smtp_host))
+        node.setAttribute('smtp_port', str(self.context.smtp_port))
+        node.setAttribute('smtp_uid', self.context.smtp_uid)
+        node.setAttribute('smtp_pwd', self.context.smtp_pwd)
+        return node
+
+    def importNode(self, node, mode=PURGE):
+        """Import the object from the DOM node.
+        """
+        self.context.smtp_host = str(node.getAttribute('smtp_host'))
+        self.context.smtp_port = int(node.getAttribute('smtp_port'))
+        self.context.smtp_uid = node.getAttribute('smtp_uid')
+        self.context.smtp_pwd = node.getAttribute('smtp_pwd')

Deleted: CMF/trunk/GenericSetup/MailHost/tests/test_adapters.py
===================================================================
--- CMF/trunk/GenericSetup/MailHost/tests/test_adapters.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/MailHost/tests/test_adapters.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,59 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""MailHost node adapter unit tests.
-
-$Id$
-"""
-
-import unittest
-import Testing
-
-import Products.Five
-import Products.GenericSetup.MailHost
-from Products.Five import zcml
-from Products.GenericSetup.testing import NodeAdapterTestCase
-from zope.app.tests.placelesssetup import PlacelessSetup
-
-
-_MAILHOST_XML = """\
-<object name="foo_mailhost" meta_type="Mail Host" smtp_host="localhost"
-   smtp_port="25" smtp_pwd="" smtp_uid=""/>
-"""
-
-
-class MailHostNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.MailHost.adapters \
-                import MailHostNodeAdapter
-
-        return MailHostNodeAdapter
-
-    def setUp(self):
-        from Products.MailHost.MailHost import MailHost
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml', Products.GenericSetup.MailHost)
-
-        self._obj = MailHost('foo_mailhost')
-        self._XML = _MAILHOST_XML
-
-
-def test_suite():
-    return unittest.TestSuite((
-        unittest.makeSuite(MailHostNodeAdapterTests),
-        ))
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')

Copied: CMF/trunk/GenericSetup/MailHost/tests/test_exportimport.py (from rev 39486, CMF/trunk/GenericSetup/MailHost/tests/test_adapters.py)
===================================================================
--- CMF/trunk/GenericSetup/MailHost/tests/test_adapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/GenericSetup/MailHost/tests/test_exportimport.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,59 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""MailHost export / import support unit tests.
+
+$Id$
+"""
+
+import unittest
+import Testing
+
+import Products.Five
+import Products.GenericSetup.MailHost
+from Products.Five import zcml
+from Products.GenericSetup.testing import NodeAdapterTestCase
+from zope.app.tests.placelesssetup import PlacelessSetup
+
+
+_MAILHOST_XML = """\
+<object name="foo_mailhost" meta_type="Mail Host" smtp_host="localhost"
+   smtp_port="25" smtp_pwd="" smtp_uid=""/>
+"""
+
+
+class MailHostNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.MailHost.exportimport \
+                import MailHostNodeAdapter
+
+        return MailHostNodeAdapter
+
+    def setUp(self):
+        from Products.MailHost.MailHost import MailHost
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml', Products.GenericSetup.MailHost)
+
+        self._obj = MailHost('foo_mailhost')
+        self._XML = _MAILHOST_XML
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(MailHostNodeAdapterTests),
+        ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Deleted: CMF/trunk/GenericSetup/PluginIndexes/adapters.py
===================================================================
--- CMF/trunk/GenericSetup/PluginIndexes/adapters.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/PluginIndexes/adapters.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,206 +0,0 @@
-##############################################################################
-#
-# 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.GenericSetup.interfaces import INodeExporter
-from Products.GenericSetup.interfaces import INodeImporter
-from Products.GenericSetup.interfaces import PURGE
-from Products.GenericSetup.utils import NodeAdapterBase
-from Products.GenericSetup.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()

Modified: CMF/trunk/GenericSetup/PluginIndexes/configure.zcml
===================================================================
--- CMF/trunk/GenericSetup/PluginIndexes/configure.zcml	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/PluginIndexes/configure.zcml	2005-10-17 18:48:24 UTC (rev 39493)
@@ -3,85 +3,85 @@
     >
 
   <adapter
-      factory=".adapters.PluggableIndexNodeAdapter"
+      factory=".exportimport.PluggableIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.PluginIndexes.interfaces.IPluggableIndex"
       />
 
   <adapter
-      factory=".adapters.PluggableIndexNodeAdapter"
+      factory=".exportimport.PluggableIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeImporter"
       for="Products.PluginIndexes.interfaces.IPluggableIndex"
       />
 
   <adapter
-      factory=".adapters.DateIndexNodeAdapter"
+      factory=".exportimport.DateIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.PluginIndexes.interfaces.IDateIndex"
       />
 
   <adapter
-      factory=".adapters.DateIndexNodeAdapter"
+      factory=".exportimport.DateIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeImporter"
       for="Products.PluginIndexes.interfaces.IDateIndex"
       />
 
   <adapter
-      factory=".adapters.DateRangeIndexNodeAdapter"
+      factory=".exportimport.DateRangeIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.PluginIndexes.interfaces.IDateRangeIndex"
       />
 
   <adapter
-      factory=".adapters.DateRangeIndexNodeAdapter"
+      factory=".exportimport.DateRangeIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeImporter"
       for="Products.PluginIndexes.interfaces.IDateRangeIndex"
       />
 
   <adapter
-      factory=".adapters.PathIndexNodeAdapter"
+      factory=".exportimport.PathIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.PluginIndexes.interfaces.IPathIndex"
       />
 
   <adapter
-      factory=".adapters.PathIndexNodeAdapter"
+      factory=".exportimport.PathIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeImporter"
       for="Products.PluginIndexes.interfaces.IPathIndex"
       />
 
   <adapter
-      factory=".adapters.VocabularyNodeAdapter"
+      factory=".exportimport.VocabularyNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.PluginIndexes.interfaces.IVocabulary"
       />
 
   <adapter
-      factory=".adapters.TextIndexNodeAdapter"
+      factory=".exportimport.TextIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.PluginIndexes.interfaces.ITextIndex"
       />
 
   <adapter
-      factory=".adapters.FilteredSetNodeAdapter"
+      factory=".exportimport.FilteredSetNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.PluginIndexes.interfaces.IFilteredSet"
       />
 
   <adapter
-      factory=".adapters.FilteredSetNodeAdapter"
+      factory=".exportimport.FilteredSetNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeImporter"
       for="Products.PluginIndexes.interfaces.IFilteredSet"
       />
 
   <adapter
-      factory=".adapters.TopicIndexNodeAdapter"
+      factory=".exportimport.TopicIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.PluginIndexes.interfaces.ITopicIndex"
       />
 
   <adapter
-      factory=".adapters.TopicIndexNodeAdapter"
+      factory=".exportimport.TopicIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeImporter"
       for="Products.PluginIndexes.interfaces.ITopicIndex"
       />

Copied: CMF/trunk/GenericSetup/PluginIndexes/exportimport.py (from rev 39486, CMF/trunk/GenericSetup/PluginIndexes/adapters.py)
===================================================================
--- CMF/trunk/GenericSetup/PluginIndexes/adapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/GenericSetup/PluginIndexes/exportimport.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -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 export / import support.
+
+$Id$
+"""
+
+from Products.GenericSetup.interfaces import INodeExporter
+from Products.GenericSetup.interfaces import INodeImporter
+from Products.GenericSetup.interfaces import PURGE
+from Products.GenericSetup.utils import NodeAdapterBase
+from Products.GenericSetup.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()

Deleted: CMF/trunk/GenericSetup/PluginIndexes/tests/test_adapters.py
===================================================================
--- CMF/trunk/GenericSetup/PluginIndexes/tests/test_adapters.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/PluginIndexes/tests/test_adapters.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,296 +0,0 @@
-##############################################################################
-#
-# 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 Products.Five
-import Products.GenericSetup.PluginIndexes
-from Products.Five import zcml
-from Products.GenericSetup.testing import NodeAdapterTestCase
-from zope.app.tests.placelesssetup import PlacelessSetup
-
-
-_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(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.PluginIndexes.adapters \
-                import DateIndexNodeAdapter
-
-        return DateIndexNodeAdapter
-
-    def setUp(self):
-        from Products.PluginIndexes.DateIndex.DateIndex import DateIndex
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml',
-                         Products.GenericSetup.PluginIndexes)
-
-        self._obj = DateIndex('foo_date')
-        self._XML = _DATE_XML
-
-
-class DateRangeIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.PluginIndexes.adapters \
-                import DateRangeIndexNodeAdapter
-
-        return DateRangeIndexNodeAdapter
-
-    def _populate(self, obj):
-        obj._edit('bar', 'baz')
-
-    def setUp(self):
-        from Products.PluginIndexes.DateRangeIndex.DateRangeIndex \
-                import DateRangeIndex
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml',
-                         Products.GenericSetup.PluginIndexes)
-
-        self._obj = DateRangeIndex('foo_daterange')
-        self._XML = _DATERANGE_XML
-
-
-class FieldIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.PluginIndexes.adapters \
-                import PluggableIndexNodeAdapter
-
-        return PluggableIndexNodeAdapter
-
-    def _populate(self, obj):
-        obj.indexed_attrs = ('bar',)
-
-    def setUp(self):
-        from Products.PluginIndexes.FieldIndex.FieldIndex import FieldIndex
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml',
-                         Products.GenericSetup.PluginIndexes)
-
-        self._obj = FieldIndex('foo_field')
-        self._XML = _FIELD_XML
-
-
-class KeywordIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.PluginIndexes.adapters \
-                import PluggableIndexNodeAdapter
-
-        return PluggableIndexNodeAdapter
-
-    def _populate(self, obj):
-        obj.indexed_attrs = ('bar',)
-
-    def setUp(self):
-        from Products.PluginIndexes.KeywordIndex.KeywordIndex \
-                import KeywordIndex
-
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml',
-                         Products.GenericSetup.PluginIndexes)
-
-        self._obj = KeywordIndex('foo_keyword')
-        self._XML = _KEYWORD_XML
-
-
-class PathIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.PluginIndexes.adapters \
-                import PathIndexNodeAdapter
-
-        return PathIndexNodeAdapter
-
-    def setUp(self):
-        from Products.PluginIndexes.PathIndex.PathIndex import PathIndex
-
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml',
-                         Products.GenericSetup.PluginIndexes)
-
-        self._obj = PathIndex('foo_path')
-        self._XML = _PATH_XML
-
-
-class VocabularyNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.PluginIndexes.adapters \
-                import VocabularyNodeAdapter
-
-        return VocabularyNodeAdapter
-
-    def setUp(self):
-        from Products.PluginIndexes.TextIndex.Vocabulary import Vocabulary
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml',
-                         Products.GenericSetup.PluginIndexes)
-
-        self._obj = Vocabulary('foo_vocabulary')
-        self._XML = _VOCABULARY_XML
-
-    def test_importNode(self):
-        pass
-
-
-class TextIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.PluginIndexes.adapters \
-                import TextIndexNodeAdapter
-
-        return TextIndexNodeAdapter
-
-    def setUp(self):
-        from Products.PluginIndexes.TextIndex.TextIndex import TextIndex
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml',
-                         Products.GenericSetup.PluginIndexes)
-
-        self._obj = TextIndex('foo_text')
-        self._XML = _TEXT_XML
-
-    def test_importNode(self):
-        pass
-
-
-class FilteredSetNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.PluginIndexes.adapters \
-                import FilteredSetNodeAdapter
-
-        return FilteredSetNodeAdapter
-
-    def _populate(self, obj):
-        obj.setExpression('True')
-
-    def setUp(self):
-        from Products.PluginIndexes.TopicIndex.FilteredSet \
-                import PythonFilteredSet
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml',
-                         Products.GenericSetup.PluginIndexes)
-
-        self._obj = PythonFilteredSet('bar', '')
-        self._XML = _SET_XML
-
-
-class TopicIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.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
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml',
-                         Products.GenericSetup.PluginIndexes)
-
-        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')

Copied: CMF/trunk/GenericSetup/PluginIndexes/tests/test_exportimport.py (from rev 39486, CMF/trunk/GenericSetup/PluginIndexes/tests/test_adapters.py)
===================================================================
--- CMF/trunk/GenericSetup/PluginIndexes/tests/test_adapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/GenericSetup/PluginIndexes/tests/test_exportimport.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,296 @@
+##############################################################################
+#
+# 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 export / import support unit tests.
+
+$Id$
+"""
+
+import unittest
+import Testing
+
+import Products.Five
+import Products.GenericSetup.PluginIndexes
+from Products.Five import zcml
+from Products.GenericSetup.testing import NodeAdapterTestCase
+from zope.app.tests.placelesssetup import PlacelessSetup
+
+
+_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(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.PluginIndexes.exportimport \
+                import DateIndexNodeAdapter
+
+        return DateIndexNodeAdapter
+
+    def setUp(self):
+        from Products.PluginIndexes.DateIndex.DateIndex import DateIndex
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml',
+                         Products.GenericSetup.PluginIndexes)
+
+        self._obj = DateIndex('foo_date')
+        self._XML = _DATE_XML
+
+
+class DateRangeIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.PluginIndexes.exportimport \
+                import DateRangeIndexNodeAdapter
+
+        return DateRangeIndexNodeAdapter
+
+    def _populate(self, obj):
+        obj._edit('bar', 'baz')
+
+    def setUp(self):
+        from Products.PluginIndexes.DateRangeIndex.DateRangeIndex \
+                import DateRangeIndex
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml',
+                         Products.GenericSetup.PluginIndexes)
+
+        self._obj = DateRangeIndex('foo_daterange')
+        self._XML = _DATERANGE_XML
+
+
+class FieldIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.PluginIndexes.exportimport \
+                import PluggableIndexNodeAdapter
+
+        return PluggableIndexNodeAdapter
+
+    def _populate(self, obj):
+        obj.indexed_attrs = ('bar',)
+
+    def setUp(self):
+        from Products.PluginIndexes.FieldIndex.FieldIndex import FieldIndex
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml',
+                         Products.GenericSetup.PluginIndexes)
+
+        self._obj = FieldIndex('foo_field')
+        self._XML = _FIELD_XML
+
+
+class KeywordIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.PluginIndexes.exportimport \
+                import PluggableIndexNodeAdapter
+
+        return PluggableIndexNodeAdapter
+
+    def _populate(self, obj):
+        obj.indexed_attrs = ('bar',)
+
+    def setUp(self):
+        from Products.PluginIndexes.KeywordIndex.KeywordIndex \
+                import KeywordIndex
+
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml',
+                         Products.GenericSetup.PluginIndexes)
+
+        self._obj = KeywordIndex('foo_keyword')
+        self._XML = _KEYWORD_XML
+
+
+class PathIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.PluginIndexes.exportimport \
+                import PathIndexNodeAdapter
+
+        return PathIndexNodeAdapter
+
+    def setUp(self):
+        from Products.PluginIndexes.PathIndex.PathIndex import PathIndex
+
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml',
+                         Products.GenericSetup.PluginIndexes)
+
+        self._obj = PathIndex('foo_path')
+        self._XML = _PATH_XML
+
+
+class VocabularyNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.PluginIndexes.exportimport \
+                import VocabularyNodeAdapter
+
+        return VocabularyNodeAdapter
+
+    def setUp(self):
+        from Products.PluginIndexes.TextIndex.Vocabulary import Vocabulary
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml',
+                         Products.GenericSetup.PluginIndexes)
+
+        self._obj = Vocabulary('foo_vocabulary')
+        self._XML = _VOCABULARY_XML
+
+    def test_importNode(self):
+        pass
+
+
+class TextIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.PluginIndexes.exportimport \
+                import TextIndexNodeAdapter
+
+        return TextIndexNodeAdapter
+
+    def setUp(self):
+        from Products.PluginIndexes.TextIndex.TextIndex import TextIndex
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml',
+                         Products.GenericSetup.PluginIndexes)
+
+        self._obj = TextIndex('foo_text')
+        self._XML = _TEXT_XML
+
+    def test_importNode(self):
+        pass
+
+
+class FilteredSetNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.PluginIndexes.exportimport \
+                import FilteredSetNodeAdapter
+
+        return FilteredSetNodeAdapter
+
+    def _populate(self, obj):
+        obj.setExpression('True')
+
+    def setUp(self):
+        from Products.PluginIndexes.TopicIndex.FilteredSet \
+                import PythonFilteredSet
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml',
+                         Products.GenericSetup.PluginIndexes)
+
+        self._obj = PythonFilteredSet('bar', '')
+        self._XML = _SET_XML
+
+
+class TopicIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.PluginIndexes.exportimport \
+                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
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml',
+                         Products.GenericSetup.PluginIndexes)
+
+        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')

Deleted: CMF/trunk/GenericSetup/ZCTextIndex/adapters.py
===================================================================
--- CMF/trunk/GenericSetup/ZCTextIndex/adapters.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/ZCTextIndex/adapters.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,110 +0,0 @@
-##############################################################################
-#
-# 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.GenericSetup.interfaces import PURGE
-from Products.GenericSetup.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()

Modified: CMF/trunk/GenericSetup/ZCTextIndex/configure.zcml
===================================================================
--- CMF/trunk/GenericSetup/ZCTextIndex/configure.zcml	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/ZCTextIndex/configure.zcml	2005-10-17 18:48:24 UTC (rev 39493)
@@ -3,25 +3,25 @@
     >
 
   <adapter
-      factory=".adapters.ZCLexiconNodeAdapter"
+      factory=".exportimport.ZCLexiconNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.ZCTextIndex.interfaces.IZCLexicon"
       />
 
   <adapter
-      factory=".adapters.ZCLexiconNodeAdapter"
+      factory=".exportimport.ZCLexiconNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeImporter"
       for="Products.ZCTextIndex.interfaces.IZCLexicon"
       />
 
   <adapter
-      factory=".adapters.ZCTextIndexNodeAdapter"
+      factory=".exportimport.ZCTextIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.ZCTextIndex.interfaces.IZCTextIndex"
       />
 
   <adapter
-      factory=".adapters.ZCTextIndexNodeAdapter"
+      factory=".exportimport.ZCTextIndexNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeImporter"
       for="Products.ZCTextIndex.interfaces.IZCTextIndex"
       />

Copied: CMF/trunk/GenericSetup/ZCTextIndex/exportimport.py (from rev 39486, CMF/trunk/GenericSetup/ZCTextIndex/adapters.py)
===================================================================
--- CMF/trunk/GenericSetup/ZCTextIndex/adapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/GenericSetup/ZCTextIndex/exportimport.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -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 export / import support.
+
+$Id$
+"""
+
+from BTrees.IOBTree import IOBTree
+from BTrees.Length import Length
+from BTrees.OIBTree import OIBTree
+
+from Products.GenericSetup.interfaces import PURGE
+from Products.GenericSetup.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()

Deleted: CMF/trunk/GenericSetup/ZCTextIndex/tests/test_adapters.py
===================================================================
--- CMF/trunk/GenericSetup/ZCTextIndex/tests/test_adapters.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/ZCTextIndex/tests/test_adapters.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,115 +0,0 @@
-##############################################################################
-#
-# 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
-
-from Acquisition import Implicit
-
-import Products.Five
-import Products.GenericSetup.ZCTextIndex
-from Products.Five import zcml
-from Products.GenericSetup.testing import NodeAdapterTestCase
-from zope.app.tests.placelesssetup import PlacelessSetup
-
-
-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(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.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
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml', Products.GenericSetup.ZCTextIndex)
-
-        self._obj = PLexicon('foo_plexicon')
-        self._XML = _PLEXICON_XML
-
-
-class ZCTextIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.ZCTextIndex.adapters \
-                import ZCTextIndexNodeAdapter
-
-        return ZCTextIndexNodeAdapter
-
-    def setUp(self):
-        from Products.ZCTextIndex.ZCTextIndex import PLexicon
-        from Products.ZCTextIndex.ZCTextIndex import ZCTextIndex
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml', Products.GenericSetup.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')

Copied: CMF/trunk/GenericSetup/ZCTextIndex/tests/test_exportimport.py (from rev 39486, CMF/trunk/GenericSetup/ZCTextIndex/tests/test_adapters.py)
===================================================================
--- CMF/trunk/GenericSetup/ZCTextIndex/tests/test_adapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/GenericSetup/ZCTextIndex/tests/test_exportimport.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,115 @@
+##############################################################################
+#
+# 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 export / import support unit tests.
+
+$Id$
+"""
+
+import unittest
+import Testing
+
+from Acquisition import Implicit
+
+import Products.Five
+import Products.GenericSetup.ZCTextIndex
+from Products.Five import zcml
+from Products.GenericSetup.testing import NodeAdapterTestCase
+from zope.app.tests.placelesssetup import PlacelessSetup
+
+
+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(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.ZCTextIndex.exportimport \
+                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
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml', Products.GenericSetup.ZCTextIndex)
+
+        self._obj = PLexicon('foo_plexicon')
+        self._XML = _PLEXICON_XML
+
+
+class ZCTextIndexNodeAdapterTests(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.ZCTextIndex.exportimport \
+                import ZCTextIndexNodeAdapter
+
+        return ZCTextIndexNodeAdapter
+
+    def setUp(self):
+        from Products.ZCTextIndex.ZCTextIndex import PLexicon
+        from Products.ZCTextIndex.ZCTextIndex import ZCTextIndex
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml', Products.GenericSetup.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')

Deleted: CMF/trunk/GenericSetup/ZCatalog/adapters.py
===================================================================
--- CMF/trunk/GenericSetup/ZCatalog/adapters.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/ZCatalog/adapters.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,125 +0,0 @@
-##############################################################################
-#
-# 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.GenericSetup.interfaces import INodeExporter
-from Products.GenericSetup.interfaces import INodeImporter
-from Products.GenericSetup.interfaces import PURGE
-from Products.GenericSetup.utils import NodeAdapterBase
-from Products.GenericSetup.utils import ObjectManagerHelpers
-from Products.GenericSetup.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:
-            exporter = INodeExporter(idx, None)
-            if exporter is None:
-                continue
-            fragment.appendChild(exporter.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)

Modified: CMF/trunk/GenericSetup/ZCatalog/configure.zcml
===================================================================
--- CMF/trunk/GenericSetup/ZCatalog/configure.zcml	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/ZCatalog/configure.zcml	2005-10-17 18:48:24 UTC (rev 39493)
@@ -3,13 +3,13 @@
     >
 
   <adapter
-      factory=".adapters.ZCatalogNodeAdapter"
+      factory=".exportimport.ZCatalogNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeExporter"
       for="Products.ZCatalog.interfaces.IZCatalog"
       />
 
   <adapter
-      factory=".adapters.ZCatalogNodeAdapter"
+      factory=".exportimport.ZCatalogNodeAdapter"
       provides="Products.GenericSetup.interfaces.INodeImporter"
       for="Products.ZCatalog.interfaces.IZCatalog"
       />

Copied: CMF/trunk/GenericSetup/ZCatalog/exportimport.py (from rev 39486, CMF/trunk/GenericSetup/ZCatalog/adapters.py)
===================================================================
--- CMF/trunk/GenericSetup/ZCatalog/adapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/GenericSetup/ZCatalog/exportimport.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,125 @@
+##############################################################################
+#
+# 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 export / import support.
+
+$Id$
+"""
+
+from Products.GenericSetup.interfaces import INodeExporter
+from Products.GenericSetup.interfaces import INodeImporter
+from Products.GenericSetup.interfaces import PURGE
+from Products.GenericSetup.utils import NodeAdapterBase
+from Products.GenericSetup.utils import ObjectManagerHelpers
+from Products.GenericSetup.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:
+            exporter = INodeExporter(idx, None)
+            if exporter is None:
+                continue
+            fragment.appendChild(exporter.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)

Deleted: CMF/trunk/GenericSetup/ZCatalog/tests/test_adapters.py
===================================================================
--- CMF/trunk/GenericSetup/ZCatalog/tests/test_adapters.py	2005-10-17 18:47:03 UTC (rev 39492)
+++ CMF/trunk/GenericSetup/ZCatalog/tests/test_adapters.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -1,159 +0,0 @@
-##############################################################################
-#
-# 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()
-
-import Products
-from Products.Five import zcml
-from Products.GenericSetup.interfaces import INodeExporter
-from Products.GenericSetup.testing import NodeAdapterTestCase
-from Products.GenericSetup.utils import PrettyDocument
-from zope.app.tests.placelesssetup import PlacelessSetup
-
-
-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(PlacelessSetup, NodeAdapterTestCase):
-
-    def _getTargetClass(self):
-        from Products.GenericSetup.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
-
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml',
-                         Products.GenericSetup.PluginIndexes)
-        zcml.load_config('configure.zcml', Products.GenericSetup.ZCatalog)
-        zcml.load_config('configure.zcml', Products.GenericSetup.ZCTextIndex)
-
-        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')

Copied: CMF/trunk/GenericSetup/ZCatalog/tests/test_exportimport.py (from rev 39486, CMF/trunk/GenericSetup/ZCatalog/tests/test_adapters.py)
===================================================================
--- CMF/trunk/GenericSetup/ZCatalog/tests/test_adapters.py	2005-10-17 15:57:08 UTC (rev 39486)
+++ CMF/trunk/GenericSetup/ZCatalog/tests/test_exportimport.py	2005-10-17 18:48:24 UTC (rev 39493)
@@ -0,0 +1,159 @@
+##############################################################################
+#
+# 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 export / import support unit tests.
+
+$Id$
+"""
+
+import unittest
+import Testing
+import Zope2
+Zope2.startup()
+
+import Products
+from Products.Five import zcml
+from Products.GenericSetup.interfaces import INodeExporter
+from Products.GenericSetup.testing import NodeAdapterTestCase
+from Products.GenericSetup.utils import PrettyDocument
+from zope.app.tests.placelesssetup import PlacelessSetup
+
+
+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(PlacelessSetup, NodeAdapterTestCase):
+
+    def _getTargetClass(self):
+        from Products.GenericSetup.ZCatalog.exportimport \
+                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
+
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('configure.zcml',
+                         Products.GenericSetup.PluginIndexes)
+        zcml.load_config('configure.zcml', Products.GenericSetup.ZCatalog)
+        zcml.load_config('configure.zcml', Products.GenericSetup.ZCTextIndex)
+
+        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')



More information about the CMF-checkins mailing list