[CMF-checkins] SVN: CMF/trunk/ merged yuppie-workflow_setup branch:

Yvo Schubbe y.2005- at wcm-solutions.de
Wed Nov 23 10:50:09 EST 2005


Log message for revision 40340:
  merged yuppie-workflow_setup branch:
  - replaced hardcoded 'Revision 2' workflow by revision2 profile
  - removed 'Classic' workflow (this is already in the CMFDefault profile)
  - removed _workflow_factories registry and related methods
  - workflows are now registered the same way as type infos in TypesTool and actions in ActionsTool
  - registered DCWorkflowDefinition the new way
  - added add view for DCWorkflowDefinition
  - added IBody to support also non-XML im- and exports
  - added some utilities for body adapters
  - moved PythonScripts setup to GenericSetup
  - moved WorkflowTool setup to CMFCore
  - moved DCWorkflowDefinition setup to DCWorkflow
  - updated profiles
  
  Note: Please svn up your Zope version! This uses five:registerClass that depends on small changes in Zope.

Changed:
  U   CMF/trunk/CHANGES.txt
  U   CMF/trunk/CMFActionIcons/DEPENDENCIES.txt
  U   CMF/trunk/CMFCalendar/DEPENDENCIES.txt
  U   CMF/trunk/CMFCore/DEPENDENCIES.txt
  U   CMF/trunk/CMFCore/WorkflowTool.py
  U   CMF/trunk/CMFCore/browser/configure.zcml
  D   CMF/trunk/CMFCore/dtml/addWorkflow.dtml
  U   CMF/trunk/CMFCore/exportimport/configure.zcml
  A   CMF/trunk/CMFCore/exportimport/tests/test_workflow.py
  A   CMF/trunk/CMFCore/exportimport/workflow.py
  U   CMF/trunk/CMFCore/tests/test_WorkflowTool.py
  U   CMF/trunk/CMFDefault/DEPENDENCIES.txt
  U   CMF/trunk/CMFDefault/profiles/default/export_steps.xml
  U   CMF/trunk/CMFDefault/profiles/default/import_steps.xml
  U   CMF/trunk/CMFDefault/profiles/default/workflows.xml
  U   CMF/trunk/CMFDefault/tests/test_DefaultWorkflow.py
  U   CMF/trunk/CMFDefault/tests/test_DiscussionReply.py
  U   CMF/trunk/CMFDefault/tests/test_Image.py
  U   CMF/trunk/CMFDefault/tests/test_Portal.py
  U   CMF/trunk/CMFDefault/tests/test_join.py
  U   CMF/trunk/CMFSetup/DEPENDENCIES.txt
  D   CMF/trunk/CMFSetup/Extensions/
  D   CMF/trunk/CMFSetup/tests/test_workflow.py
  U   CMF/trunk/CMFSetup/utils.py
  U   CMF/trunk/CMFSetup/workflow.py
  D   CMF/trunk/CMFSetup/xml/wtcToolExport.xml
  D   CMF/trunk/CMFSetup/xml/wtcWorkflowExport.xml
  U   CMF/trunk/CMFTopic/DEPENDENCIES.txt
  U   CMF/trunk/CMFTopic/profiles/default/workflows.xml
  U   CMF/trunk/CMFTopic/tests/test_DateC.py
  U   CMF/trunk/CMFUid/DEPENDENCIES.txt
  U   CMF/trunk/DCWorkflow/DCWorkflow.py
  U   CMF/trunk/DCWorkflow/DEPENDENCIES.txt
  D   CMF/trunk/DCWorkflow/Default.py
  A   CMF/trunk/DCWorkflow/Extensions/
  U   CMF/trunk/DCWorkflow/__init__.py
  A   CMF/trunk/DCWorkflow/browser/
  A   CMF/trunk/DCWorkflow/configure.zcml
  A   CMF/trunk/DCWorkflow/exportimport.py
  A   CMF/trunk/DCWorkflow/interfaces.py
  A   CMF/trunk/DCWorkflow/profiles/
  U   CMF/trunk/DCWorkflow/tests/test_DCWorkflow.py
  A   CMF/trunk/DCWorkflow/tests/test_exportimport.py
  U   CMF/trunk/DCWorkflow/tests/test_guard.py
  U   CMF/trunk/DCWorkflow/utils.py
  A   CMF/trunk/DCWorkflow/xml/
  U   CMF/trunk/GenericSetup/DEPENDENCIES.txt
  A   CMF/trunk/GenericSetup/PythonScripts/
  U   CMF/trunk/GenericSetup/configure.zcml
  U   CMF/trunk/GenericSetup/interfaces.py
  U   CMF/trunk/GenericSetup/testing.py
  U   CMF/trunk/GenericSetup/tests/common.py
  U   CMF/trunk/GenericSetup/utils.py

-=-
Modified: CMF/trunk/CHANGES.txt
===================================================================
--- CMF/trunk/CHANGES.txt	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CHANGES.txt	2005-11-23 15:50:07 UTC (rev 40340)
@@ -2,6 +2,18 @@
 
   New Features
 
+    - WorkflowTool and DCWorkflow: Improved add form for workflow objects.
+      Presettings can now be loaded from workflow settings in setup profiles.
+      This replaces the feature that did allow to load presettings from the
+      oldstyle workflow factories registry.
+
+    - WorkflowTool: Switched to generic plug-in mechanism for workflows.
+      Any class registered for IWorkflowDefinition can now be used in the
+      WorkflowTool.
+
+    - DCWorkflow: Added 'revision2' profile.
+      This replaces the hardcoded 'Revision 2' default workflow.
+
     - CMFActionIcons, CMFCalendar, CMFDefault, CMFTopic, CMFUid:
       use the new 'for_' argument in GenericSetup's profile registry API
       to indicate that profiles are intended for CMFCore's ISiteRoot sites.
@@ -147,6 +159,8 @@
 
   Others
 
+    - DCWorkflow: Removed hardcoded default workflows.
+
     - Workflow: Removed deprecated WorkflowInformation and getActionsFor.
 
     - CMFCore and GenericSetup: Moved mechanisms for content export / import

Modified: CMF/trunk/CMFActionIcons/DEPENDENCIES.txt
===================================================================
--- CMF/trunk/CMFActionIcons/DEPENDENCIES.txt	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFActionIcons/DEPENDENCIES.txt	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,4 +1,4 @@
-Zope >= 2.8.2
+Zope >= 2.8.5
 Five >= 1.2
 CMFCore
 GenericSetup

Modified: CMF/trunk/CMFCalendar/DEPENDENCIES.txt
===================================================================
--- CMF/trunk/CMFCalendar/DEPENDENCIES.txt	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFCalendar/DEPENDENCIES.txt	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,4 +1,4 @@
-Zope >= 2.8.2
+Zope >= 2.8.5
 Five >= 1.2
 CMFCore
 CMFDefault

Modified: CMF/trunk/CMFCore/DEPENDENCIES.txt
===================================================================
--- CMF/trunk/CMFCore/DEPENDENCIES.txt	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFCore/DEPENDENCIES.txt	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,3 +1,3 @@
-Zope >= 2.8.2
+Zope >= 2.8.5
 Five >= 1.2
 GenericSetup

Modified: CMF/trunk/CMFCore/WorkflowTool.py
===================================================================
--- CMF/trunk/CMFCore/WorkflowTool.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFCore/WorkflowTool.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -23,9 +23,11 @@
 from Globals import InitializeClass
 from Globals import PersistentMapping
 from OFS.Folder import Folder
+from OFS.ObjectManager import IFAwareObjectManager
 from zope.interface import implements
 
 from ActionProviderBase import ActionProviderBase
+from interfaces import IWorkflowDefinition
 from interfaces import IWorkflowTool
 from interfaces.portal_workflow import portal_workflow as z2IWorkflowTool
 from permissions import ManagePortal
@@ -40,7 +42,8 @@
 _marker = []  # Create a new marker object.
 
 
-class WorkflowTool(UniqueObject, Folder, ActionProviderBase):
+class WorkflowTool(UniqueObject, IFAwareObjectManager, Folder,
+                   ActionProviderBase):
 
     """ Mediator tool, mapping workflow objects
     """
@@ -50,6 +53,7 @@
 
     id = 'portal_workflow'
     meta_type = 'CMF Workflow Tool'
+    _product_interfaces = (IWorkflowDefinition,)
 
     _chains_by_type = None  # PersistentMapping
     _default_chain = ('default_workflow',)
@@ -69,37 +73,6 @@
     security.declareProtected( ManagePortal, 'manage_overview' )
     manage_overview = DTMLFile( 'explainWorkflowTool', _dtmldir )
 
-    _manage_addWorkflowForm = DTMLFile('addWorkflow', _dtmldir)
-
-    security.declareProtected( ManagePortal, 'manage_addWorkflowForm')
-    def manage_addWorkflowForm(self, REQUEST):
-
-        """ Form for adding workflows.
-        """
-        wft = []
-        for key in _workflow_factories.keys():
-            wft.append(key)
-        wft.sort()
-        return self._manage_addWorkflowForm(REQUEST, workflow_types=wft)
-
-    security.declareProtected( ManagePortal, 'manage_addWorkflow')
-    def manage_addWorkflow(self, workflow_type, id, RESPONSE=None):
-
-        """ Adds a workflow from the registered types.
-        """
-        factory = _workflow_factories[workflow_type]
-        ob = factory(id)
-        self._setObject(id, ob)
-        if RESPONSE is not None:
-            RESPONSE.redirect(self.absolute_url() +
-                              '/manage_main?management_view=Contents')
-
-    def all_meta_types(self):
-        return (
-            {'name': 'Workflow',
-             'action': 'manage_addWorkflowForm',
-             'permission': ManagePortal },)
-
     _manage_selectWorkflows = DTMLFile('selectWorkflows', _dtmldir)
 
     security.declareProtected( ManagePortal, 'manage_selectWorkflows')
@@ -426,8 +399,7 @@
         self._default_chain = tuple(ids)
 
     security.declareProtected( ManagePortal, 'setChainForPortalTypes')
-    def setChainForPortalTypes(self, pt_names, chain):
-
+    def setChainForPortalTypes(self, pt_names, chain, verify=True):
         """ Set a chain for a specific portal type.
         """
         cbt = self._chains_by_type
@@ -437,12 +409,12 @@
         if isinstance(chain, basestring):
             chain = [ wf.strip() for wf in chain.split(',') if wf.strip() ]
 
-        ti = self._listTypeInfo()
-        for t in ti:
-            id = t.getId()
-            if id in pt_names:
-                cbt[id] = tuple(chain)
+        ti_ids = [ t.getId() for t in self._listTypeInfo() ]
 
+        for type_id in pt_names:
+            if verify and not (type_id in ti_ids):
+                continue
+            cbt[type_id] = tuple(chain)
 
     security.declareProtected( ManagePortal, 'updateRoleMappings')
     def updateRoleMappings(self, REQUEST=None):
@@ -464,11 +436,11 @@
 
     security.declarePrivate('getWorkflowById')
     def getWorkflowById(self, wf_id):
-
         """ Retrieve a given workflow.
         """
         wf = getattr(self, wf_id, None)
-        if getattr(wf, '_isAWorkflow', 0):
+        if getattr(wf, '_isAWorkflow', False) or \
+                IWorkflowDefinition.providedBy(wf):
             return wf
         else:
             return None
@@ -651,29 +623,3 @@
             ob.reindexObjectSecurity()
 
 InitializeClass(WorkflowTool)
-
-
-_workflow_factories = {}
-
-def _makeWorkflowFactoryKey(factory, id=None, title=None):
-    # The factory should take one argument, id.
-    if id is None:
-        id = getattr(factory, 'id', '') or getattr(factory, 'meta_type', '')
-    if title is None:
-        title = getattr(factory, 'title', '')
-    key = id
-    if title:
-        key = key + ' (%s)' % title
-    return key
-
-def addWorkflowFactory(factory, id=None, title=None):
-    key = _makeWorkflowFactoryKey( factory, id, title )
-    _workflow_factories[key] = factory
-
-def _removeWorkflowFactory( factory, id=None, title=None ):
-    """ Make teardown in unitcase cleaner. """
-    key = _makeWorkflowFactoryKey( factory, id, title )
-    try:
-        del _workflow_factories[key]
-    except KeyError:
-        pass

Modified: CMF/trunk/CMFCore/browser/configure.zcml
===================================================================
--- CMF/trunk/CMFCore/browser/configure.zcml	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFCore/browser/configure.zcml	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,9 +1,12 @@
 <configure
-  xmlns="http://namespaces.zope.org/zope"
-  xmlns:browser="http://namespaces.zope.org/browser"
-  i18n_domain="cmf"
-  >
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    xmlns:five="http://namespaces.zope.org/five"
+    i18n_domain="cmf"
+    >
 
+  <five:traversable class="Products.CMFCore.WorkflowTool.WorkflowTool"/>
+
   <!-- Set up default menus as action categories. -->
   <browser:menu
     id="object"

Deleted: CMF/trunk/CMFCore/dtml/addWorkflow.dtml
===================================================================
--- CMF/trunk/CMFCore/dtml/addWorkflow.dtml	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFCore/dtml/addWorkflow.dtml	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,44 +0,0 @@
-<dtml-let form_title="'Add workflow'">
-<dtml-var manage_page_header>
-<dtml-var manage_form_title>
-</dtml-let>
-
-<form action="manage_addWorkflow" method="POST">
-<table cellspacing="0" cellpadding="2" border="0">
-  <tr>
-    <td align="left" valign="top">
-    <div class="form-label">
-    Id
-    </div>
-    </td>
-    <td align="left" valign="top">
-    <input type="text" name="id" size="40" />
-    </td>
-  </tr>
-  <tr>
-    <td align="left" valign="top">
-    <div class="form-label">
-    Type
-    </label></div>
-    </td>
-    <td align="left" valign="top">
-    <dtml-in workflow_types>
-      <input type="radio" name="workflow_type" value="&dtml-sequence-item;">
-      &dtml-sequence-item;<br />
-    </dtml-in>
-    </td>
-  </tr>
-  <tr>
-    <td align="left" valign="top">
-    </td>
-    <td align="left" valign="top">
-    <div class="form-element">
-    <input class="form-element" type="submit" name="submit" 
-     value=" Add " /> 
-    </div>
-    </td>
-  </tr>
-</table>
-</form>
-
-<dtml-var manage_page_footer>

Modified: CMF/trunk/CMFCore/exportimport/configure.zcml
===================================================================
--- CMF/trunk/CMFCore/exportimport/configure.zcml	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFCore/exportimport/configure.zcml	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,7 +1,5 @@
 <configure
     xmlns="http://namespaces.zope.org/zope"
-    xmlns:five="http://namespaces.zope.org/five"
-    i18n_domain="cmf"
     >
 
   <adapter
@@ -124,4 +122,11 @@
       for="Products.CMFCore.interfaces.ITypeInformation"
       />
 
+  <adapter
+      factory=".workflow.WorkflowToolXMLAdapter"
+      provides="Products.GenericSetup.interfaces.IBody"
+      for="Products.CMFCore.interfaces.IWorkflowTool
+           Products.GenericSetup.interfaces.ISetupContext"
+      />
+
 </configure>

Copied: CMF/trunk/CMFCore/exportimport/tests/test_workflow.py (from rev 40338, CMF/branches/yuppie-workflow_setup/CMFCore/exportimport/tests/test_workflow.py)

Copied: CMF/trunk/CMFCore/exportimport/workflow.py (from rev 40338, CMF/branches/yuppie-workflow_setup/CMFCore/exportimport/workflow.py)

Modified: CMF/trunk/CMFCore/tests/test_WorkflowTool.py
===================================================================
--- CMF/trunk/CMFCore/tests/test_WorkflowTool.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFCore/tests/test_WorkflowTool.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -20,9 +20,7 @@
 
 from OFS.SimpleItem import SimpleItem
 
-from Products.CMFCore.tests.base.testcase import WarningInterceptor
 
-
 class Dummy( SimpleItem ):
 
     def __init__( self, id ):
@@ -131,24 +129,15 @@
         return None
 
 
-class WorkflowToolTests(unittest.TestCase, WarningInterceptor):
+class WorkflowToolTests(unittest.TestCase):
 
-    def setUp( self ):
-        from Products.CMFCore.WorkflowTool import addWorkflowFactory
-        addWorkflowFactory( DummyWorkflow )
-
-    def tearDown( self ):
-        from Products.CMFCore.WorkflowTool import _removeWorkflowFactory
-        _removeWorkflowFactory( DummyWorkflow )
-        self._free_warning_output()
-
     def _makeOne( self, workflow_ids=() ):
         from Products.CMFCore.WorkflowTool import WorkflowTool
 
         tool = WorkflowTool()
 
         for workflow_id in workflow_ids:
-            tool.manage_addWorkflow( DummyWorkflow.meta_type, workflow_id )
+            tool._setObject(workflow_id, DummyWorkflow(workflow_id))
 
         return tool
 

Modified: CMF/trunk/CMFDefault/DEPENDENCIES.txt
===================================================================
--- CMF/trunk/CMFDefault/DEPENDENCIES.txt	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFDefault/DEPENDENCIES.txt	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,4 +1,4 @@
-Zope >= 2.8.2
+Zope >= 2.8.5
 Five >= 1.2
 CMFCore
 GenericSetup

Modified: CMF/trunk/CMFDefault/profiles/default/export_steps.xml
===================================================================
--- CMF/trunk/CMFDefault/profiles/default/export_steps.xml	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFDefault/profiles/default/export_steps.xml	2005-11-23 15:50:07 UTC (rev 40340)
@@ -61,7 +61,7 @@
   Export types tool's type information objects.
  </export-step>
  <export-step id="workflows"
-              handler="Products.CMFSetup.workflow.exportWorkflowTool"
+              handler="Products.CMFCore.exportimport.workflow.exportWorkflowTool"
               title="Workflow Tool">
   Export workflow tool's workflow definitions and supporting scripts.
  </export-step>

Modified: CMF/trunk/CMFDefault/profiles/default/import_steps.xml
===================================================================
--- CMF/trunk/CMFDefault/profiles/default/import_steps.xml	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFDefault/profiles/default/import_steps.xml	2005-11-23 15:50:07 UTC (rev 40340)
@@ -73,10 +73,9 @@
   Import various settings from PortalGenerator.
  </import-step>
  <import-step id="workflow" version="20040630-01"
-              handler="Products.CMFSetup.workflow.importWorkflowTool"
+              handler="Products.CMFCore.exportimport.workflow.importWorkflowTool"
               title="Workflow Tool">
   <dependency step="toolset"/>
-  <dependency step="typeinfo"/>
   Import workflow tool's workflow definitions and supporting scripts.
  </import-step>
 </import-steps>

Modified: CMF/trunk/CMFDefault/profiles/default/workflows.xml
===================================================================
--- CMF/trunk/CMFDefault/profiles/default/workflows.xml	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFDefault/profiles/default/workflows.xml	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,17 +1,12 @@
 <?xml version="1.0"?>
-<workflow-tool>
- <workflow workflow_id="default_workflow"
-           meta_type="Workflow"
-           filename="workflows/default_workflow/definition.xml"/>
+<object name="portal_workflow" meta_type="CMF Workflow Tool">
+ <property name="title"></property>
+ <object name="default_workflow" meta_type="Workflow"/>
  <bindings>
   <default>
    <bound-workflow workflow_id="default_workflow"/>
   </default>
-  <type type_id="CMF BTree Folder">
-
-  </type>
-  <type type_id="Folder">
-
-  </type>
+  <type type_id="CMF BTree Folder"/>
+  <type type_id="Folder"/>
  </bindings>
-</workflow-tool>
+</object>

Modified: CMF/trunk/CMFDefault/tests/test_DefaultWorkflow.py
===================================================================
--- CMF/trunk/CMFDefault/tests/test_DefaultWorkflow.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFDefault/tests/test_DefaultWorkflow.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -15,37 +15,32 @@
 $Id$
 """
 
-from unittest import TestCase, TestSuite, makeSuite, main
+import unittest
 import Testing
-import Zope2
-Zope2.startup()
 
 from Products.CMFCore.tests.base.dummy import DummyContent
 from Products.CMFCore.tests.base.dummy import DummySite
 from Products.CMFCore.tests.base.dummy import DummyTool
 from Products.CMFCore.tests.base.dummy import DummyUserFolder
 
-from Products.CMFCore.WorkflowTool import addWorkflowFactory
 from Products.CMFCore.WorkflowTool import WorkflowTool
 
-from Products.CMFDefault.MembershipTool import MembershipTool
-from Products.CMFDefault.DefaultWorkflow import DefaultWorkflowDefinition
 
-class DefaultWorkflowDefinitionTests(TestCase):
+class DefaultWorkflowDefinitionTests(unittest.TestCase):
 
     def setUp(self):
-
+        from Products.CMFDefault.DefaultWorkflow \
+                import DefaultWorkflowDefinition
         self.site = DummySite('site')
         self.site._setObject('portal_types', DummyTool())
         self.site._setObject('portal_workflow', WorkflowTool())
-        self.site._setObject('portal_membership', MembershipTool())
+        self.site._setObject('portal_membership', DummyTool())
         self.site._setObject('acl_users', DummyUserFolder())
 
-        addWorkflowFactory(DefaultWorkflowDefinition,
-                           id='default_workflow', title='default_workflow')
+        wftool = self.site.portal_workflow
+        wftool._setObject('wf', DefaultWorkflowDefinition('wf'))
+        wftool.setDefaultChain('wf')
 
-        self._constructDummyWorkflow()
-
     def test_z2interfaces(self):
         from Interface.Verify import verifyClass
         from Products.CMFCore.interfaces.portal_workflow \
@@ -63,12 +58,6 @@
 
         verifyClass(IWorkflowDefinition, DefaultWorkflowDefinition)
 
-    def _constructDummyWorkflow(self):
-
-        wftool = self.site.portal_workflow
-        wftool.manage_addWorkflow('default_workflow (default_workflow)', 'wf')
-        wftool.setDefaultChain('wf')
-
     def _getDummyWorkflow(self):
         wftool = self.site.portal_workflow
         return wftool.wf
@@ -92,10 +81,11 @@
 
     # XXX more tests...
 
+
 def test_suite():
-    return TestSuite((
-        makeSuite( DefaultWorkflowDefinitionTests ),
+    return unittest.TestSuite((
+        unittest.makeSuite(DefaultWorkflowDefinitionTests),
         ))
 
 if __name__ == '__main__':
-    main(defaultTest='test_suite')
+    unittest.main(defaultTest='test_suite')

Modified: CMF/trunk/CMFDefault/tests/test_DiscussionReply.py
===================================================================
--- CMF/trunk/CMFDefault/tests/test_DiscussionReply.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFDefault/tests/test_DiscussionReply.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -15,10 +15,8 @@
 $Id$
 """
 
-from unittest import TestSuite, makeSuite, main
+import unittest
 import Testing
-import Zope2
-Zope2.startup()
 
 import Products
 from AccessControl.SecurityManagement import newSecurityManager
@@ -35,8 +33,10 @@
         PlacelessSetup.setUp(self)
         RequestTest.setUp(self)
         zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('permissions.zcml', Products.Five)
         zcml.load_config('configure.zcml', Products.GenericSetup)
         zcml.load_config('configure.zcml', Products.CMFCore)
+        zcml.load_config('configure.zcml', Products.DCWorkflow)
         try:
             factory = self.root.manage_addProduct['CMFDefault'].addConfiguredSite
             factory('cmf', 'CMFDefault:default', snapshot=False)
@@ -90,10 +90,10 @@
 
 
 def test_suite():
-    suite = TestSuite()
-    suite.addTest(makeSuite(DiscussionReplyTest))
-    suite.addTest(makeSuite(DiscussionReplyTestMember))
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(DiscussionReplyTest))
+    suite.addTest(unittest.makeSuite(DiscussionReplyTestMember))
     return suite
 
 if __name__ == '__main__':
-    main(defaultTest='test_suite')
+    unittest.main(defaultTest='test_suite')

Modified: CMF/trunk/CMFDefault/tests/test_Image.py
===================================================================
--- CMF/trunk/CMFDefault/tests/test_Image.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFDefault/tests/test_Image.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -100,8 +100,10 @@
         PlacelessSetup.setUp(self)
         RequestTest.setUp(self)
         zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('permissions.zcml', Products.Five)
         zcml.load_config('configure.zcml', Products.GenericSetup)
         zcml.load_config('configure.zcml', Products.CMFCore)
+        zcml.load_config('configure.zcml', Products.DCWorkflow)
         try:
             newSecurityManager(None, UnrestrictedUser('manager', '', ['Manager'], []))
             factory = self.root.manage_addProduct['CMFDefault'].addConfiguredSite

Modified: CMF/trunk/CMFDefault/tests/test_Portal.py
===================================================================
--- CMF/trunk/CMFDefault/tests/test_Portal.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFDefault/tests/test_Portal.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -15,10 +15,8 @@
 $Id$
 """
 
-from unittest import TestSuite, makeSuite, main
+import unittest
 import Testing
-import Zope2
-Zope2.startup()
 
 import Products
 from Acquisition import aq_base
@@ -51,8 +49,10 @@
         PlacelessSetup.setUp(self)
         SecurityRequestTest.setUp(self)
         zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('permissions.zcml', Products.Five)
         zcml.load_config('configure.zcml', Products.GenericSetup)
         zcml.load_config('configure.zcml', Products.CMFCore)
+        zcml.load_config('configure.zcml', Products.DCWorkflow)
 
     def tearDown(self):
         SecurityRequestTest.tearDown(self)
@@ -207,9 +207,9 @@
 
 
 def test_suite():
-    return TestSuite((
-        makeSuite(CMFSiteTests),
+    return unittest.TestSuite((
+        unittest.makeSuite(CMFSiteTests),
         ))
 
 if __name__ == '__main__':
-    main(defaultTest='test_suite')
+    unittest.main(defaultTest='test_suite')

Modified: CMF/trunk/CMFDefault/tests/test_join.py
===================================================================
--- CMF/trunk/CMFDefault/tests/test_join.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFDefault/tests/test_join.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -15,16 +15,31 @@
 $Id$
 """
 
-from unittest import TestSuite, makeSuite, main
+import unittest
 import Testing
-import Zope2
-Zope2.startup()
 
+import Products
+from Products.Five import zcml
+
+from Products.CMFCore.tests.base.testcase import PlacelessSetup
 from Products.CMFCore.tests.base.testcase import TransactionalTest
 
 
-class MembershipTests( TransactionalTest ):
+class MembershipTests(PlacelessSetup, TransactionalTest):
 
+    def setUp(self):
+        PlacelessSetup.setUp(self)
+        TransactionalTest.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('permissions.zcml', Products.Five)
+        zcml.load_config('configure.zcml', Products.GenericSetup)
+        zcml.load_config('configure.zcml', Products.CMFCore)
+        zcml.load_config('configure.zcml', Products.DCWorkflow)
+
+    def tearDown(self):
+        TransactionalTest.tearDown(self)
+        PlacelessSetup.tearDown(self)
+
     def _makePortal(self):
         # Create a portal instance suitable for testing
         factory = self.root.manage_addProduct['CMFDefault'].addConfiguredSite
@@ -101,9 +116,9 @@
 
 
 def test_suite():
-    return TestSuite((
-        makeSuite(MembershipTests),
+    return unittest.TestSuite((
+        unittest.makeSuite(MembershipTests),
         ))
 
 if __name__ == '__main__':
-    main(defaultTest='test_suite')
+    unittest.main(defaultTest='test_suite')

Modified: CMF/trunk/CMFSetup/DEPENDENCIES.txt
===================================================================
--- CMF/trunk/CMFSetup/DEPENDENCIES.txt	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFSetup/DEPENDENCIES.txt	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,5 +1,4 @@
-Zope >= 2.8.2
+Zope >= 2.8.5
 Five >= 1.2
 CMFCore
-DCWorkflow
 GenericSetup

Deleted: CMF/trunk/CMFSetup/tests/test_workflow.py
===================================================================
--- CMF/trunk/CMFSetup/tests/test_workflow.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFSetup/tests/test_workflow.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,2674 +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 export / import of DCWorkflows and bindings.
-
-$Id$
-"""
-
-import unittest
-import Testing
-import Zope2
-Zope2.startup()
-
-from OFS.Folder import Folder
-from Products.PythonScripts.PythonScript import PythonScript
-from Products.ExternalMethod.ExternalMethod import ExternalMethod
-
-from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition
-from Products.DCWorkflow.Transitions import TRIGGER_USER_ACTION
-from Products.DCWorkflow.Transitions import TRIGGER_AUTOMATIC
-from Products.GenericSetup.tests.common import BaseRegistryTests
-from Products.GenericSetup.tests.common import DummyExportContext
-from Products.GenericSetup.tests.common import DummyImportContext
-
-
-class DummyWorkflowTool( Folder ):
-
-    def __init__( self, id='portal_workflow' ):
-        Folder.__init__( self, id )
-        self._default_chain = ()
-        self._chains_by_type = {}
-
-    def getWorkflowIds( self ):
-
-        return self.objectIds()
-
-    def getWorkflowById( self, workflow_id ):
-
-        return self._getOb( workflow_id )
-
-    def setDefaultChain( self, chain ):
-
-        chain = chain.replace( ',', ' ' )
-        self._default_chain = tuple( chain.split() )
-
-    def setChainForPortalTypes( self, pt_names, chain ):
-
-        chain = chain.replace( ',', ' ' )
-        chain = tuple( chain.split() )
-
-        if self._chains_by_type is None:
-            self._chains_by_type = {}
-
-        for pt_name in pt_names:
-            self._chains_by_type[ pt_name ] = chain
-
-class DummyWorkflow( Folder ):
-
-    meta_type = 'Dummy Workflow'
-
-class _GuardChecker:
-
-    def _genGuardProps( self, permissions, roles, groups, expr ):
-
-        return { 'guard_permissions'   : '; '.join( permissions )
-               , 'guard_roles'         : '; '.join( roles )
-               , 'guard_groups'        : '; '.join( groups )
-               , 'guard_expr'          : expr
-               }
-
-    def _assertGuard( self, info, permissions, roles, groups, expr ):
-
-        self.assertEqual( len( info[ 'guard_permissions' ] )
-                        , len( permissions ) )
-
-        for expected in permissions:
-            self.failUnless( expected in info[ 'guard_permissions' ] )
-
-        self.assertEqual( len( info[ 'guard_roles' ] )
-                        , len( roles ) )
-
-        for expected in roles:
-            self.failUnless( expected in info[ 'guard_roles' ] )
-
-        self.assertEqual( len( info[ 'guard_groups' ] )
-                        , len( groups ) )
-
-        for expected in groups:
-            self.failUnless( expected in info[ 'guard_groups' ] )
-
-        self.assertEqual( info[ 'guard_expr' ], expr )
-
-
-class _WorkflowSetup( BaseRegistryTests ):
-
-    def _initSite( self ):
-
-        self.root.site = Folder( id='site' )
-        site = self.root.site
-        self.root.site.portal_workflow = DummyWorkflowTool()
-
-        return site
-
-    def _initDCWorkflow( self, workflow_id ):
-
-        wf_tool = self.root.site.portal_workflow
-        wf_tool._setObject( workflow_id, DCWorkflowDefinition( workflow_id ) )
-
-        return wf_tool._getOb( workflow_id )
-
-    def _initVariables( self, dcworkflow ):
-
-        for id, args in _WF_VARIABLES.items():
-
-            dcworkflow.variables.addVariable( id )
-            variable = dcworkflow.variables._getOb( id )
-
-            ( descr, def_val, def_exp, for_cat, for_stat, upd_alw
-            ) = args[ :-4 ]
-
-            variable.setProperties( description=args[0]
-                                  , default_value=args[1]
-                                  , default_expr=args[2]
-                                  , for_catalog=args[3]
-                                  , for_status=args[4]
-                                  , update_always=args[5]
-                                  , props=self._genGuardProps( *args[ -4: ] )
-                                  )
-
-    def _initStates( self, dcworkflow ):
-
-        dcworkflow.groups = _WF_GROUPS
-
-        for k, v in _WF_STATES.items():
-
-            dcworkflow.states.addState( k )
-            state = dcworkflow.states._getOb( k )
-
-            state.setProperties( title=v[ 0 ]
-                               , description=v[ 1 ]
-                               , transitions=v[ 2 ]
-                               )
-            if not v[ 3 ]:
-                state.permission_roles = {}
-
-            for permission, roles in v[ 3 ].items():
-                state.setPermission( permission
-                                   , not isinstance( roles, tuple )
-                                   , roles
-                                   )
-            faux_request = {}
-
-            for group_id, roles in v[ 4 ]:
-                for role in roles:
-                    faux_request[ '%s|%s' % ( group_id, role ) ] = True
-
-            state.setGroups( REQUEST=faux_request )
-
-            for k, v in v[ 5 ].items():
-                state.addVariable( k, v )
-
-    def _initTransitions( self, dcworkflow ):
-
-        for k, v in _WF_TRANSITIONS.items():
-
-            dcworkflow.transitions.addTransition( k )
-            transition = dcworkflow.transitions._getOb( k )
-
-            transition.setProperties( title=v[ 0 ]
-                                    , description=v[ 1 ]
-                                    , new_state_id=v[ 2 ]
-                                    , trigger_type=v[ 3 ]
-                                    , script_name=v[ 4 ]
-                                    , after_script_name=v[ 5 ]
-                                    , actbox_name=v[ 6 ]
-                                    , actbox_url=v[ 7 ]
-                                    , actbox_category=v[ 8 ]
-                                    , props=self._genGuardProps( *v[ -4: ] )
-                                    )
-
-            for k, v in v[ 9 ].items():
-                transition.addVariable( k, v )
-
-    def _initWorklists( self, dcworkflow ):
-
-        for k, v in _WF_WORKLISTS.items():
-
-            dcworkflow.worklists.addWorklist( k )
-            worklist = dcworkflow.worklists._getOb( k )
-
-            worklist.title = v[ 0 ]
-
-            props=self._genGuardProps( *v[ -4: ] )
-
-            for var_id, matches in v[ 2 ].items():
-                props[ 'var_match_%s' % var_id ] = ';'.join( matches )
-
-            worklist.setProperties( description=v[ 1 ]
-                                  , actbox_name=v[ 3 ]
-                                  , actbox_url=v[ 4 ]
-                                  , actbox_category=v[ 5 ]
-                                  , props=props
-                                  )
-
-    def _initScripts( self, dcworkflow ):
-
-        for k, v in _WF_SCRIPTS.items():
-
-            if v[ 0 ] == PythonScript.meta_type:
-                script = PythonScript( k )
-                script.write( v[ 1 ] )
-
-            elif v[ 0 ] == ExternalMethod.meta_type:
-                script = ExternalMethod(k,'', v[3], v[4])
-
-            else:
-                raise ValueError, 'Unknown script type: %s' % v[ 0 ]
-
-            dcworkflow.scripts._setObject( k, script )
-
-class WorkflowToolConfiguratorTests( _WorkflowSetup ):
-    
-    def _getTargetClass( self ):
-
-        from Products.CMFSetup.workflow import WorkflowToolConfigurator
-        return WorkflowToolConfigurator
-
-    def test_listWorkflowInfo_empty( self ):
-
-        site = self._initSite()
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        self.assertEqual( len( configurator.listWorkflowInfo() ), 0 )
-
-    def test_listWorkflowInfo_mixed( self ):
-
-        from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition
-
-        site = self._initSite()
-
-        WF_ID_NON = 'non_dcworkflow'
-        WF_TITLE_NON = 'Non-DCWorkflow'
-        WF_ID_DC = 'dcworkflow'
-        WF_TITLE_DC = 'DCWorkflow'
-
-        site = self._initSite()
-
-        wf_tool = site.portal_workflow
-        nondcworkflow = DummyWorkflow( WF_TITLE_NON )
-        nondcworkflow.title = WF_TITLE_NON
-        wf_tool._setObject( WF_ID_NON, nondcworkflow )
-
-        dcworkflow = self._initDCWorkflow( WF_ID_DC )
-        dcworkflow.title = WF_TITLE_DC
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        info_list = configurator.listWorkflowInfo()
-
-        self.assertEqual( len( info_list ), 2 )
-
-        non_info = [ x for x in info_list if x[ 'id' ] == WF_ID_NON ][0]
-        self.assertEqual( non_info[ 'title' ], WF_TITLE_NON )
-        self.assertEqual( non_info[ 'meta_type' ], DummyWorkflow.meta_type )
-
-        dc_info = [ x for x in info_list if x[ 'id' ] == WF_ID_DC ][0]
-        self.assertEqual( dc_info[ 'title' ], WF_TITLE_DC )
-        self.assertEqual( dc_info[ 'meta_type' ]
-                        , DCWorkflowDefinition.meta_type )
-        self.assertEqual( dc_info[ 'filename' ]
-                        , 'workflows/%s/definition.xml' % WF_ID_DC )
-
-    def test_listWorkflowChains_no_default( self ):
-
-        site = self._initSite()
-        configurator = self._makeOne( site ).__of__( site )
-
-        chains = configurator.listWorkflowChains()
-
-        default_chain = [ x[1] for x in chains if x[0] is None ][0]
-        self.assertEqual( len( default_chain ), 0 )
-
-    def test_listWorkflowChains_with_default( self ):
-
-        site = self._initSite()
-        site.portal_workflow._default_chain = ( 'foo', 'bar' )
-        configurator = self._makeOne( site ).__of__( site )
-
-        chains = configurator.listWorkflowChains()
-
-        self.assertEqual( chains[ 0 ][ 0 ], None )
-        default_chain = chains[ 0 ][ 1 ]
-        self.assertEqual( len( default_chain ), 2 )
-        self.assertEqual( default_chain[ 0 ], 'foo' )
-        self.assertEqual( default_chain[ 1 ], 'bar' )
-
-    def test_listWorkflowChains_no_overrides( self ):
-
-        site = self._initSite()
-        configurator = self._makeOne( site ).__of__( site )
-
-        chains = configurator.listWorkflowChains()
-
-        self.assertEqual( len( chains ), 1 )
-
-    def test_listWorkflowChains_with_overrides( self ):
-
-        site = self._initSite()
-        site.portal_workflow._chains_by_type[ 'qux' ] = ( 'foo', 'bar' )
-        configurator = self._makeOne( site ).__of__( site )
-
-        chains = configurator.listWorkflowChains()
-
-        self.assertEqual( len( chains ), 2 )
-
-        self.assertEqual( chains[ 0 ][ 0 ], None )
-        default_chain = chains[ 0 ][ 1 ]
-        self.assertEqual( len( default_chain ), 0 )
-
-        self.assertEqual( chains[ 1 ][ 0 ], 'qux' )
-        qux_chain = chains[ 1 ][ 1 ]
-        self.assertEqual( len( qux_chain ), 2 )
-        self.assertEqual( qux_chain[ 0 ], 'foo' )
-        self.assertEqual( qux_chain[ 1 ], 'bar' )
-
-    def test_listWorkflowChains_default_chain_plus_overrides( self ):
-
-        site = self._initSite()
-        site.portal_workflow._default_chain = ( 'foo', 'bar' )
-        site.portal_workflow._chains_by_type[ 'qux' ] = ( 'baz', )
-        configurator = self._makeOne( site ).__of__( site )
-
-        chains = configurator.listWorkflowChains()
-
-        self.assertEqual( chains[ 0 ][ 0 ], None )
-        default_chain = chains[ 0 ][ 1 ]
-        self.assertEqual( len( default_chain ), 2 )
-        self.assertEqual( default_chain[ 0 ], 'foo' )
-        self.assertEqual( default_chain[ 1 ], 'bar' )
-
-        self.assertEqual( chains[ 1 ][ 0 ], 'qux' )
-        qux_chain = chains[ 1 ][ 1 ]
-        self.assertEqual( len( qux_chain ), 1 )
-        self.assertEqual( qux_chain[ 0 ], 'baz' )
-
-    def test_generateXML_empty( self ):
-
-        site = self._initSite()
-        configurator = self._makeOne( site ).__of__( site )
-        self._compareDOM( configurator.generateXML(), _EMPTY_TOOL_EXPORT )
-
-    def test_generateXML_default_chain_plus_overrides( self ):
-
-        site = self._initSite()
-        site.portal_workflow._default_chain = ( 'foo', 'bar' )
-        site.portal_workflow._chains_by_type[ 'qux' ] = ( 'baz', )
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        self._compareDOM( configurator.generateXML()
-                        , _OVERRIDE_TOOL_EXPORT )
-
-    def test_generateXML_mixed( self ):
-
-        WF_ID_NON = 'non_dcworkflow'
-        WF_TITLE_NON = 'Non-DCWorkflow'
-        WF_ID_DC = 'dcworkflow'
-        WF_TITLE_DC = 'DCWorkflow'
-
-        site = self._initSite()
-
-        wf_tool = site.portal_workflow
-        nondcworkflow = DummyWorkflow( WF_TITLE_NON )
-        nondcworkflow.title = WF_TITLE_NON
-        wf_tool._setObject( WF_ID_NON, nondcworkflow )
-
-        dcworkflow = self._initDCWorkflow( WF_ID_DC )
-        dcworkflow.title = WF_TITLE_DC
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        self._compareDOM( configurator.generateXML(), _NORMAL_TOOL_EXPORT )
-
-    def test_parseXML_empty( self ):
-
-        site = self._initSite()
-        configurator = self._makeOne( site ).__of__( site )
-
-        tool_info = configurator.parseXML( _EMPTY_TOOL_EXPORT )
-
-        self.assertEqual( len( tool_info[ 'workflows' ] ), 0 )
-        self.assertEqual( len( tool_info[ 'bindings' ] ), 1 )
-
-    def test_parseXML_default_chain_plus_overrides( self ):
-
-        site = self._initSite()
-        configurator = self._makeOne( site ).__of__( site )
-
-        tool_info = configurator.parseXML( _OVERRIDE_TOOL_EXPORT )
-
-        self.assertEqual( len( tool_info[ 'workflows' ] ), 0 )
-        self.assertEqual( len( tool_info[ 'bindings' ] ), 2 )
-
-        default = tool_info[ 'bindings' ][ None ]
-        self.assertEqual( len( default ), 2 )
-        self.assertEqual( default[ 0 ], 'foo' )
-        self.assertEqual( default[ 1 ], 'bar' )
-
-        override = tool_info[ 'bindings' ][ 'qux' ]
-        self.assertEqual( len( override ), 1 )
-        self.assertEqual( override[ 0 ], 'baz' )
-
-    def test_parseXML_normal( self ):
-
-        site = self._initSite()
-        configurator = self._makeOne( site ).__of__( site )
-
-        tool_info = configurator.parseXML( _NORMAL_TOOL_EXPORT )
-
-        self.assertEqual( len( tool_info[ 'workflows' ] ), 2 )
-
-        info = tool_info[ 'workflows' ][ 0 ]
-        self.assertEqual( info[ 'workflow_id' ], 'non_dcworkflow' )
-        self.assertEqual( info[ 'meta_type' ], DummyWorkflow.meta_type )
-        self.assertEqual( info[ 'filename' ], None )
-
-        info = tool_info[ 'workflows' ][ 1 ]
-        self.assertEqual( info[ 'workflow_id' ], 'dcworkflow' )
-        self.assertEqual( info[ 'meta_type' ], DCWorkflowDefinition.meta_type )
-        self.assertEqual( info[ 'filename' ],
-                          'workflows/dcworkflow/definition.xml' )
-
-        self.assertEqual( len( tool_info[ 'bindings' ] ), 1 )
-
-
-class WorkflowDefinitionConfiguratorTests( _WorkflowSetup, _GuardChecker ):
-
-    def _getTargetClass( self ):
-
-        from Products.CMFSetup.workflow import WorkflowDefinitionConfigurator
-        return WorkflowDefinitionConfigurator
-
-    def test_getWorkflowInfo_non_dcworkflow( self ):
-
-        WF_ID = 'dummy'
-        WF_TITLE = 'Dummy'
-
-        site = self._initSite()
-        wf_tool = site.portal_workflow
-        dummy = DummyWorkflow( WF_TITLE )
-        wf_tool._setObject( WF_ID, dummy )
-
-        dummy.title = WF_TITLE
-
-        configurator = self._makeOne( site ).__of__( site )
-        info = configurator.getWorkflowInfo( WF_ID )
-
-        self.assertEqual( info[ 'id' ], WF_ID )
-        self.assertEqual( info[ 'meta_type' ], DummyWorkflow.meta_type )
-        self.assertEqual( info[ 'title' ], WF_TITLE )
-
-    def test_getWorkflowInfo_dcworkflow_defaults( self ):
-
-        WF_ID = 'dcworkflow_defaults'
-
-        site = self._initSite()
-        dcworkflow = self._initDCWorkflow( WF_ID )
-
-        configurator = self._makeOne( site ).__of__( site )
-        info = configurator.getWorkflowInfo( WF_ID )
-
-        self.assertEqual( info[ 'id' ], WF_ID )
-        self.assertEqual( info[ 'meta_type' ], DCWorkflowDefinition.meta_type )
-        self.assertEqual( info[ 'title' ], dcworkflow.title )
-
-        self.assertEqual( info[ 'state_variable' ], dcworkflow.state_var )
-
-        self.assertEqual( len( info[ 'permissions' ] ), 0 )
-        self.assertEqual( len( info[ 'variable_info' ] ), 0 )
-        self.assertEqual( len( info[ 'state_info' ] ), 0 )
-        self.assertEqual( len( info[ 'transition_info' ] ), 0 )
-
-    def test_getWorkflowInfo_dcworkflow_permissions( self ):
-
-        WF_ID = 'dcworkflow_permissions'
-
-        site = self._initSite()
-        dcworkflow = self._initDCWorkflow( WF_ID )
-        dcworkflow.permissions = _WF_PERMISSIONS
-
-        configurator = self._makeOne( site ).__of__( site )
-        info = configurator.getWorkflowInfo( WF_ID )
-
-        permissions = info[ 'permissions' ]
-        self.assertEqual( len( permissions ), len( _WF_PERMISSIONS ) )
-
-        for permission in _WF_PERMISSIONS:
-            self.failUnless( permission in permissions )
-
-    def test_getWorkflowInfo_dcworkflow_variables( self ):
-
-        WF_ID = 'dcworkflow_variables'
-
-        site = self._initSite()
-        dcworkflow = self._initDCWorkflow( WF_ID )
-        self._initVariables( dcworkflow )
-
-        configurator = self._makeOne( site ).__of__( site )
-        info = configurator.getWorkflowInfo( WF_ID )
-
-        variable_info = info[ 'variable_info' ]
-        self.assertEqual( len( variable_info ), len( _WF_VARIABLES ) )
-
-        ids = [ x[ 'id' ] for x in variable_info ]
-
-        for k in _WF_VARIABLES.keys():
-            self.failUnless( k in ids )
-
-        for info in variable_info:
-
-            expected = _WF_VARIABLES[ info[ 'id' ] ]
-
-            self.assertEqual( info[ 'description' ], expected[ 0 ] )
-            self.assertEqual( info[ 'default_value' ], expected[ 1 ] )
-            self.assertEqual( info[ 'default_expr' ], expected[ 2 ] )
-            self.assertEqual( info[ 'for_catalog' ], expected[ 3 ] )
-            self.assertEqual( info[ 'for_status' ], expected[ 4 ] )
-            self.assertEqual( info[ 'update_always' ], expected[ 5 ] )
-
-            self._assertGuard( info, *expected[ -4: ] )
-
-    def test_getWorkflowInfo_dcworkflow_states( self ):
-
-        WF_ID = 'dcworkflow_states'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-        dcworkflow = self._initDCWorkflow( WF_ID )
-        dcworkflow.initial_state = WF_INITIAL_STATE
-        self._initStates( dcworkflow )
-
-        configurator = self._makeOne( site ).__of__( site )
-        info = configurator.getWorkflowInfo( WF_ID )
-
-        self.assertEqual( info[ 'state_variable' ], dcworkflow.state_var )
-        self.assertEqual( info[ 'initial_state' ], dcworkflow.initial_state )
-
-        state_info = info[ 'state_info' ]
-        self.assertEqual( len( state_info ), len( _WF_STATES ) )
-
-        ids = [ x[ 'id' ] for x in state_info ]
-
-        for k in _WF_STATES.keys():
-            self.failUnless( k in ids )
-
-        for info in state_info:
-
-            expected = _WF_STATES[ info[ 'id' ] ]
-
-            self.assertEqual( info[ 'title' ], expected[ 0 ] )
-            self.assertEqual( info[ 'description' ], expected[ 1 ] )
-            self.assertEqual( info[ 'transitions' ], expected[ 2 ] )
-
-            permissions = info[ 'permissions' ]
-
-            self.assertEqual( len( permissions ), len( expected[ 3 ] ) )
-
-            for ep_id, ep_roles in expected[ 3 ].items():
-
-                fp = [ x for x in permissions if x[ 'name' ] == ep_id ][ 0 ]
-
-                self.assertEqual( fp[ 'acquired' ]
-                                , not isinstance( ep_roles, tuple ) )
-
-                self.assertEqual( len( fp[ 'roles' ] ), len( ep_roles ) )
-
-                for ep_role in ep_roles:
-                    self.failUnless( ep_role in fp[ 'roles' ] )
-
-            groups = info[ 'groups' ]
-            self.assertEqual( len( groups ), len( expected[ 4 ] ) )
-
-            for i in range( len( groups ) ):
-                self.assertEqual( groups[ i ], expected[ 4 ][ i ] )
-
-            variables = info[ 'variables' ]
-            self.assertEqual( len( variables ), len( expected[ 5 ] ) )
-
-            for v_info in variables:
-
-                name, type, value = ( v_info[ 'name' ]
-                                    , v_info[ 'type' ], v_info[ 'value' ] )
-
-                self.assertEqual( value, expected[ 5 ][ name ] )
-
-                if isinstance( value, bool ):
-                    self.assertEqual( type, 'bool' )
-                elif isinstance( value, int ):
-                    self.assertEqual( type, 'int' )
-                elif isinstance( value, float ):
-                    self.assertEqual( type, 'float' )
-                elif isinstance( value, basestring ):
-                    self.assertEqual( type, 'string' )
-
-    def test_getWorkflowInfo_dcworkflow_transitions( self ):
-
-        from Products.CMFSetup.workflow import TRIGGER_TYPES
-
-        WF_ID = 'dcworkflow_transitions'
-
-        site = self._initSite()
-        dcworkflow = self._initDCWorkflow( WF_ID )
-        self._initTransitions( dcworkflow )
-
-        configurator = self._makeOne( site ).__of__( site )
-        info = configurator.getWorkflowInfo( WF_ID )
-
-        transition_info = info[ 'transition_info' ]
-        self.assertEqual( len( transition_info ), len( _WF_TRANSITIONS ) )
-
-        ids = [ x[ 'id' ] for x in transition_info ]
-
-        for k in _WF_TRANSITIONS.keys():
-            self.failUnless( k in ids )
-
-        for info in transition_info:
-
-            expected = _WF_TRANSITIONS[ info[ 'id' ] ]
-
-            self.assertEqual( info[ 'title' ], expected[ 0 ] )
-            self.assertEqual( info[ 'description' ], expected[ 1 ] )
-            self.assertEqual( info[ 'new_state_id' ], expected[ 2 ] )
-            self.assertEqual( info[ 'trigger_type' ]
-                            , TRIGGER_TYPES[ expected[ 3 ] ] )
-            self.assertEqual( info[ 'script_name' ], expected[ 4 ] )
-            self.assertEqual( info[ 'after_script_name' ], expected[ 5 ] )
-            self.assertEqual( info[ 'actbox_name' ], expected[ 6 ] )
-            self.assertEqual( info[ 'actbox_url' ], expected[ 7 ] )
-            self.assertEqual( info[ 'actbox_category' ], expected[ 8 ] )
-
-            variables = info[ 'variables' ]
-            self.assertEqual( len( variables ), len( expected[ 9 ] ) )
-
-            for v_info in variables:
-                self.assertEqual( v_info[ 'expr' ]
-                                , expected[ 9 ][ v_info[ 'name' ] ] )
-
-            self._assertGuard( info, *expected[ -4: ] )
-
-    def test_getWorkflowInfo_dcworkflow_worklists( self ):
-
-        WF_ID = 'dcworkflow_worklists'
-
-        site = self._initSite()
-        dcworkflow = self._initDCWorkflow( WF_ID )
-        self._initWorklists( dcworkflow )
-
-        configurator = self._makeOne( site ).__of__( site )
-        info = configurator.getWorkflowInfo( WF_ID )
-
-        worklist_info = info[ 'worklist_info' ]
-        self.assertEqual( len( worklist_info ), len( _WF_WORKLISTS ) )
-
-        ids = [ x[ 'id' ] for x in worklist_info ]
-
-        for k in _WF_WORKLISTS.keys():
-            self.failUnless( k in ids )
-
-        for info in worklist_info:
-
-            expected = _WF_WORKLISTS[ info[ 'id' ] ]
-
-            self.assertEqual( info[ 'title' ], expected[ 0 ] )
-            self.assertEqual( info[ 'description' ], expected[ 1 ] )
-            self.assertEqual( info[ 'actbox_name' ], expected[ 3 ] )
-            self.assertEqual( info[ 'actbox_url' ], expected[ 4 ] )
-            self.assertEqual( info[ 'actbox_category' ], expected[ 5 ] )
-
-            var_match = info[ 'var_match' ]
-            self.assertEqual( len( var_match ), len( expected[ 2 ] ) )
-
-            for var_id, values_txt in var_match:
-
-                values = [ x.strip() for x in values_txt.split( ';' ) ]
-                e_values = expected[ 2 ][ var_id ]
-                self.assertEqual( len( values ), len( e_values ) )
-
-                for e_value in e_values:
-                    self.failUnless( e_value in values )
-
-            self._assertGuard( info, *expected[ -4: ] )
-
-    def test_getWorkflowInfo_dcworkflow_scripts( self ):
-
-        WF_ID = 'dcworkflow_scripts'
-
-        site = self._initSite()
-        dcworkflow = self._initDCWorkflow( WF_ID )
-        self._initScripts( dcworkflow )
-
-        configurator = self._makeOne( site ).__of__( site )
-        info = configurator.getWorkflowInfo( WF_ID )
-
-        script_info = info[ 'script_info' ]
-        self.assertEqual( len( script_info ), len( _WF_SCRIPTS ) )
-
-        ids = [ x[ 'id' ] for x in script_info ]
-
-        for k in _WF_SCRIPTS.keys():
-            self.failUnless( k in ids )
-
-        for info in script_info:
-
-            expected = _WF_SCRIPTS[ info[ 'id' ] ]
-
-            self.assertEqual( info[ 'meta_type' ], expected[ 0 ] )
-            self.assertEqual( info[ 'body' ], expected[ 1 ] )
-
-            if info[ 'meta_type' ] == PythonScript.meta_type:
-                self.assertEqual( info[ 'filename' ]
-                                , expected[ 2 ] % WF_ID )
-            else:
-                self.assertEqual( info[ 'filename' ], expected[ 2 ] )
-
-    def test_generateXML_empty( self ):
-
-        WF_ID = 'empty'
-        WF_TITLE = 'Empty DCWorkflow'
-        WF_INITIAL_STATE = 'initial'
-
-        site = self._initSite()
-        dcworkflow = self._initDCWorkflow( WF_ID )
-        dcworkflow.title = WF_TITLE
-        dcworkflow.initial_state = WF_INITIAL_STATE
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        self._compareDOM( configurator.generateWorkflowXML( WF_ID )
-                        , _EMPTY_WORKFLOW_EXPORT % ( WF_ID
-                                                   , WF_TITLE
-                                                   , WF_INITIAL_STATE
-                                                   ) )
-
-    def test_generateWorkflowXML_nondc( self ):
-
-        WF_ID_NON = 'non_dcworkflow'
-        WF_TITLE_NON = 'Non-DCWorkflow'
-
-        site = self._initSite()
-
-        wf_tool = site.portal_workflow
-        nondcworkflow = DummyWorkflow( WF_TITLE_NON )
-        nondcworkflow.title = WF_TITLE_NON
-        wf_tool._setObject( WF_ID_NON, nondcworkflow )
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        self.assertEqual( configurator.generateWorkflowXML( WF_ID_NON ), None )
-
-    def test_generateWorkflowXML_normal( self ):
-
-        WF_ID = 'normal'
-        WF_TITLE = 'Normal DCWorkflow'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-        dcworkflow = self._initDCWorkflow( WF_ID )
-        dcworkflow.title = WF_TITLE
-        dcworkflow.initial_state = WF_INITIAL_STATE
-        dcworkflow.permissions = _WF_PERMISSIONS
-        self._initVariables( dcworkflow )
-        self._initStates( dcworkflow )
-        self._initTransitions( dcworkflow )
-        self._initWorklists( dcworkflow )
-        self._initScripts( dcworkflow )
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        self._compareDOM( configurator.generateWorkflowXML( WF_ID )
-                        , _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID
-                            , 'title' : WF_TITLE
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID.replace(' ', '_')
-                            } )
-
-    def test_generateWorkflowXML_multiple( self ):
-
-        WF_ID_1 = 'dc1'
-        WF_TITLE_1 = 'Normal DCWorkflow #1'
-        WF_ID_2 = 'dc2'
-        WF_TITLE_2 = 'Normal DCWorkflow #2'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-
-        dcworkflow_1 = self._initDCWorkflow( WF_ID_1 )
-        dcworkflow_1.title = WF_TITLE_1
-        dcworkflow_1.initial_state = WF_INITIAL_STATE
-        dcworkflow_1.permissions = _WF_PERMISSIONS
-        self._initVariables( dcworkflow_1 )
-        self._initStates( dcworkflow_1 )
-        self._initTransitions( dcworkflow_1 )
-        self._initWorklists( dcworkflow_1 )
-        self._initScripts( dcworkflow_1 )
-
-        dcworkflow_2 = self._initDCWorkflow( WF_ID_2 )
-        dcworkflow_2.title = WF_TITLE_2
-        dcworkflow_2.initial_state = WF_INITIAL_STATE
-        dcworkflow_2.permissions = _WF_PERMISSIONS
-        self._initVariables( dcworkflow_2 )
-        self._initStates( dcworkflow_2 )
-        self._initTransitions( dcworkflow_2 )
-        self._initWorklists( dcworkflow_2 )
-        self._initScripts( dcworkflow_2 )
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        self._compareDOM( configurator.generateWorkflowXML( WF_ID_1 )
-                        , _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID_1
-                            , 'title' : WF_TITLE_1
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID_1.replace(' ', '_')
-                            } )
-
-        self._compareDOM( configurator.generateWorkflowXML( WF_ID_2 )
-                        , _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID_2
-                            , 'title' : WF_TITLE_2
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID_2.replace(' ', '_')
-                            } )
-
-    def test_parseWorkflowXML_empty( self ):
-
-        WF_ID = 'empty'
-        WF_TITLE = 'Empty DCWorkflow'
-        WF_INITIAL_STATE = 'initial'
-
-        site = self._initSite()
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        ( workflow_id
-        , title
-        , state_variable
-        , initial_state
-        , states
-        , transitions
-        , variables
-        , worklists
-        , permissions
-        , scripts
-        ) = configurator.parseWorkflowXML( _EMPTY_WORKFLOW_EXPORT
-                                         % ( WF_ID
-                                           , WF_TITLE
-                                           , WF_INITIAL_STATE
-                                           ) )
-
-        self.assertEqual( len( states ), 0 )
-        self.assertEqual( len( transitions ), 0 )
-        self.assertEqual( len( variables ), 0 )
-        self.assertEqual( len( worklists ), 0 )
-        self.assertEqual( len( permissions ), 0 )
-        self.assertEqual( len( scripts ), 0 )
-
-    def test_parseWorkflowXML_normal_attribs( self ):
-
-        WF_ID = 'normal'
-        WF_TITLE = 'Normal DCWorkflow'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        ( workflow_id
-        , title
-        , state_variable
-        , initial_state
-        , states
-        , transitions
-        , variables
-        , worklists
-        , permissions
-        , scripts
-        ) = configurator.parseWorkflowXML(
-                          _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID
-                            , 'title' : WF_TITLE
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID.replace(' ', '_')
-                            } )
-
-        self.assertEqual( workflow_id, WF_ID )
-        self.assertEqual( title, WF_TITLE )
-        self.assertEqual( state_variable, 'state' )
-        self.assertEqual( initial_state, WF_INITIAL_STATE )
-
-    def test_parseWorkflowXML_normal_states( self ):
-
-        WF_ID = 'normal'
-        WF_TITLE = 'Normal DCWorkflow'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        ( workflow_id
-        , title
-        , state_variable
-        , initial_state
-        , states
-        , transitions
-        , variables
-        , worklists
-        , permissions
-        , scripts
-        ) = configurator.parseWorkflowXML(
-                          _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID
-                            , 'title' : WF_TITLE
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID.replace(' ', '_')
-                            } )
-
-        self.assertEqual( len( states ), len( _WF_STATES ) )
-
-        for state in states:
-
-            state_id = state[ 'state_id' ]
-            self.failUnless( state_id in _WF_STATES )
-
-            expected = _WF_STATES[ state_id ]
-
-            self.assertEqual( state[ 'title' ], expected[ 0 ] )
-
-            description = ''.join( state[ 'description' ] )
-            self.failUnless( expected[ 1 ] in description )
-
-            self.assertEqual( tuple( state[ 'transitions' ] ), expected[ 2 ] )
-            self.assertEqual( state[ 'permissions' ], expected[ 3 ] )
-            self.assertEqual( tuple( state[ 'groups' ] )
-                            , tuple( expected[ 4 ] ) )
-
-            for k, v_info in state[ 'variables' ].items():
-
-                exp_value = expected[ 5 ][ k ]
-                self.assertEqual( v_info[ 'value' ], str( exp_value ) )
-
-                if isinstance( exp_value, bool ):
-                    self.assertEqual( v_info[ 'type' ], 'bool' )
-                elif isinstance( exp_value, int ):
-                    self.assertEqual( v_info[ 'type' ], 'int' )
-                elif isinstance( exp_value, float ):
-                    self.assertEqual( v_info[ 'type' ], 'float' )
-                elif isinstance( exp_value, basestring ):
-                    self.assertEqual( v_info[ 'type' ], 'string' )
-
-    def test_parseWorkflowXML_normal_transitions( self ):
-
-        from Products.CMFSetup.workflow import TRIGGER_TYPES
-
-        WF_ID = 'normal'
-        WF_TITLE = 'Normal DCWorkflow'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        ( workflow_id
-        , title
-        , state_variable
-        , initial_state
-        , states
-        , transitions
-        , variables
-        , worklists
-        , permissions
-        , scripts
-        ) = configurator.parseWorkflowXML(
-                          _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID
-                            , 'title' : WF_TITLE
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID.replace(' ', '_')
-                            } )
-
-        self.assertEqual( len( transitions ), len( _WF_TRANSITIONS ) )
-
-        for transition in transitions:
-
-            transition_id = transition[ 'transition_id' ]
-            self.failUnless( transition_id in _WF_TRANSITIONS )
-
-            expected = _WF_TRANSITIONS[ transition_id ]
-
-            self.assertEqual( transition[ 'title' ], expected[ 0 ] )
-
-            description = ''.join( transition[ 'description' ] )
-            self.failUnless( expected[ 1 ] in description )
-
-            self.assertEqual( transition[ 'new_state' ], expected[ 2 ] )
-            self.assertEqual( transition[ 'trigger' ]
-                            , TRIGGER_TYPES[ expected[ 3 ] ] )
-            self.assertEqual( transition[ 'before_script' ], expected[ 4 ] )
-            self.assertEqual( transition[ 'after_script' ]
-                            , expected[ 5 ] )
-
-            action = transition[ 'action' ]
-            self.assertEqual( action.get( 'name', '' ), expected[ 6 ] )
-            self.assertEqual( action.get( 'url', '' ), expected[ 7 ] )
-            self.assertEqual( action.get( 'category', '' ), expected[ 8 ] )
-
-            self.assertEqual( transition[ 'variables' ], expected[ 9 ] )
-
-            guard = transition[ 'guard' ]
-            self.assertEqual( tuple( guard.get( 'permissions', () ) )
-                            , expected[ 10 ] )
-            self.assertEqual( tuple( guard.get( 'roles', () ) )
-                            , expected[ 11 ] )
-            self.assertEqual( tuple( guard.get( 'groups', () ) )
-                            , expected[ 12 ] )
-            self.assertEqual( guard.get( 'expression', '' ), expected[ 13 ] )
-
-    def test_parseWorkflowXML_normal_variables( self ):
-
-        from Products.CMFSetup.workflow import TRIGGER_TYPES
-
-        WF_ID = 'normal'
-        WF_TITLE = 'Normal DCWorkflow'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        ( workflow_id
-        , title
-        , state_variable
-        , initial_state
-        , states
-        , transitions
-        , variables
-        , worklists
-        , permissions
-        , scripts
-        ) = configurator.parseWorkflowXML(
-                          _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID
-                            , 'title' : WF_TITLE
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID.replace(' ', '_')
-                            } )
-
-        self.assertEqual( len( variables ), len( _WF_VARIABLES ) )
-
-        for variable in variables:
-
-            variable_id = variable[ 'variable_id' ]
-            self.failUnless( variable_id in _WF_VARIABLES )
-
-            expected = _WF_VARIABLES[ variable_id ]
-
-            description = ''.join( variable[ 'description' ] )
-            self.failUnless( expected[ 0 ] in description )
-
-            default = variable[ 'default' ]
-            self.assertEqual( default[ 'value' ], expected[ 1 ] )
-
-            exp_type = 'n/a'
-
-            if expected[ 1 ]:
-                exp_value = expected[ 1 ]
-
-                if isinstance( exp_value, bool ):
-                    exp_type = 'bool'
-                elif isinstance( exp_value, int ):
-                    exp_type = 'int'
-                elif isinstance( exp_value, float ):
-                    exp_type = 'float'
-                elif isinstance( exp_value, basestring ):
-                    exp_type = 'string'
-                else:
-                    exp_type = 'XXX'
-
-            self.assertEqual( default[ 'type' ], exp_type )
-            self.assertEqual( default[ 'expression' ], expected[ 2 ] )
-
-            self.assertEqual( variable[ 'for_catalog' ], expected[ 3 ] )
-            self.assertEqual( variable[ 'for_status' ], expected[ 4 ] )
-            self.assertEqual( variable[ 'update_always' ], expected[ 5 ] )
-
-            guard = variable[ 'guard' ]
-            self.assertEqual( tuple( guard.get( 'permissions', () ) )
-                            , expected[ 6 ] )
-            self.assertEqual( tuple( guard.get( 'roles', () ) )
-                            , expected[ 7 ] )
-            self.assertEqual( tuple( guard.get( 'groups', () ) )
-                            , expected[ 8 ] )
-            self.assertEqual( guard.get( 'expression', '' ), expected[ 9 ] )
-
-    def test_parseWorkflowXML_normal_worklists( self ):
-
-        from Products.CMFSetup.workflow import TRIGGER_TYPES
-
-        WF_ID = 'normal'
-        WF_TITLE = 'Normal DCWorkflow'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        ( workflow_id
-        , title
-        , state_variable
-        , initial_state
-        , states
-        , transitions
-        , variables
-        , worklists
-        , permissions
-        , scripts
-        ) = configurator.parseWorkflowXML(
-                          _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID
-                            , 'title' : WF_TITLE
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID.replace(' ', '_')
-                            } )
-
-        self.assertEqual( len( worklists ), len( _WF_WORKLISTS ) )
-
-        for worklist in worklists:
-
-            worklist_id = worklist[ 'worklist_id' ]
-            self.failUnless( worklist_id in _WF_WORKLISTS )
-
-            expected = _WF_WORKLISTS[ worklist_id ]
-
-            self.assertEqual( worklist[ 'title' ], expected[ 0 ] )
-
-            description = ''.join( worklist[ 'description' ] )
-            self.failUnless( expected[ 1 ] in description )
-
-            self.assertEqual( tuple( worklist[ 'match' ] )
-                            , tuple( expected[ 2 ] ) )
-
-            action = worklist[ 'action' ]
-            self.assertEqual( action.get( 'name', '' ), expected[ 3 ] )
-            self.assertEqual( action.get( 'url', '' ), expected[ 4 ] )
-            self.assertEqual( action.get( 'category', '' ), expected[ 5 ] )
-
-            guard = worklist[ 'guard' ]
-            self.assertEqual( tuple( guard.get( 'permissions', () ) )
-                            , expected[ 6 ] )
-            self.assertEqual( tuple( guard.get( 'roles', () ) )
-                            , expected[ 7 ] )
-            self.assertEqual( tuple( guard.get( 'groups', () ) )
-                            , expected[ 8 ] )
-            self.assertEqual( guard.get( 'expression', '' ), expected[ 9 ] )
-
-    def test_parseWorkflowXML_normal_permissions( self ):
-
-        from Products.CMFSetup.workflow import TRIGGER_TYPES
-
-        WF_ID = 'normal'
-        WF_TITLE = 'Normal DCWorkflow'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        ( workflow_id
-        , title
-        , state_variable
-        , initial_state
-        , states
-        , transitions
-        , variables
-        , worklists
-        , permissions
-        , scripts
-        ) = configurator.parseWorkflowXML(
-                          _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID
-                            , 'title' : WF_TITLE
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID.replace(' ', '_')
-                            } )
-
-        self.assertEqual( len( permissions ), len( _WF_PERMISSIONS ) )
-
-        for permission in permissions:
-
-            self.failUnless( permission in _WF_PERMISSIONS )
-
-    def test_parseWorkflowXML_normal_scripts( self ):
-
-        from Products.CMFSetup.workflow import TRIGGER_TYPES
-
-        WF_ID = 'normal'
-        WF_TITLE = 'Normal DCWorkflow'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-
-        configurator = self._makeOne( site ).__of__( site )
-
-        ( workflow_id
-        , title
-        , state_variable
-        , initial_state
-        , states
-        , transitions
-        , variables
-        , worklists
-        , permissions
-        , scripts
-        ) = configurator.parseWorkflowXML(
-                          _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID
-                            , 'title' : WF_TITLE
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID.replace(' ', '_')
-                            } )
-
-        self.assertEqual( len( scripts ), len( _WF_SCRIPTS ) )
-
-        for script in scripts:
-
-            script_id = script[ 'script_id' ]
-            self.failUnless( script_id in _WF_SCRIPTS )
-
-            expected = _WF_SCRIPTS[ script_id ]
-
-            self.assertEqual( script[ 'meta_type' ], expected[ 0 ] )
-
-            # Body is not kept as part of the workflow XML
-
-            if script[ 'meta_type' ] == PythonScript.meta_type:
-                self.assertEqual( script[ 'filename' ]
-                                , expected[ 2 ] % workflow_id )
-            else:
-                self.assertEqual( script[ 'filename' ], expected[ 2 ] )
-
-
-_WF_PERMISSIONS = \
-( 'Open content for modifications'
-, 'Modify content'
-, 'Query history'
-, 'Restore expired content'
-)
-
-_WF_GROUPS = \
-( 'Content_owners'
-, 'Content_assassins'
-)
-
-_WF_VARIABLES = \
-{ 'when_opened':  ( 'Opened when'
-                  , ''
-                  , "python:None"
-                  , True
-                  , False
-                  , True
-                  , ( 'Query history', 'Open content for modifications' )
-                  , ()
-                  , ()
-                  , ""
-                  )
-, 'when_expired': ( 'Expired when'
-                  , ''
-                  , "nothing"
-                  , True
-                  , False
-                  , True
-                  , ( 'Query history', 'Open content for modifications' )
-                  , ()
-                  , ()
-                  , ""
-                  )
-, 'killed_by':    ( 'Killed by'
-                  , 'n/a'
-                  , ""
-                  , True
-                  , False
-                  , True
-                  , ()
-                  , ( 'Hangman', 'Sherrif' )
-                  , ()
-                  , ""
-                  )
-}
-
-_WF_STATES = \
-{ 'closed':  ( 'Closed'
-             , 'Closed for modifications'
-             , ( 'open', 'kill', 'expire' )
-             , { 'Modify content':  () }
-             , ()
-             , { 'is_opened':  False, 'is_closed':  True }
-             )
-, 'opened':  ( 'Opened'
-             , 'Open for modifications'
-             , ( 'close', 'kill', 'expire' )
-             , { 'Modify content':  [ 'Owner', 'Manager' ] }
-             , [ ( 'Content_owners', ( 'Owner', ) ) ]
-             , { 'is_opened':  True, 'is_closed':  False }
-             )
-, 'killed':  ( 'Killed'
-             , 'Permanently unavailable'
-             , ()
-             , {}
-             , ()
-             , {}
-             )
-, 'expired': ( 'Expired'
-             , 'Expiration date has passed'
-             , ( 'open', )
-             , { 'Modify content':  [ 'Owner', 'Manager' ] }
-             , ()
-             , { 'is_opened':  False, 'is_closed':  False }
-             )
-}
-
-_WF_TRANSITIONS = \
-{ 'open':    ( 'Open'
-             , 'Open the object for modifications'
-             , 'opened'
-             , TRIGGER_USER_ACTION
-             , 'before_open'
-             , ''
-             , 'Open'
-             , 'string:${object_url}/open_for_modifications'
-             , 'workflow'
-             , { 'when_opened' : 'object/ZopeTime' }
-             , ( 'Open content for modifications', )
-             , ()
-             , ()
-             , ""
-             )
-, 'close':   ( 'Close'
-             , 'Close the object for modifications'
-             , 'closed'
-             , TRIGGER_USER_ACTION
-             , ''
-             , 'after_close'
-             , 'Close'
-             , 'string:${object_url}/close_for_modifications'
-             , 'workflow'
-             , {}
-             , ()
-             , ( 'Owner', 'Manager' )
-             , ()
-             , ""
-             )
-, 'kill':    ( 'Kill'
-             , 'Make the object permanently unavailable.'
-             , 'killed'
-             , TRIGGER_USER_ACTION
-             , ''
-             , 'after_kill'
-             , 'Kill'
-             , 'string:${object_url}/kill_object'
-             , 'workflow'
-             , { 'killed_by' : 'string:${user/getId}' }
-             , ()
-             , ()
-             , ( 'Content_assassins', )
-             , ""
-             )
-, 'expire':  ( 'Expire'
-             , 'Retire objects whose expiration is past.'
-             , 'expired'
-             , TRIGGER_AUTOMATIC
-             , 'before_expire'
-             , ''
-             , ''
-             , ''
-             , ''
-             , { 'when_expired' : 'object/ZopeTime' }
-             , ()
-             , ()
-             , ()
-             , "python: object.expiration() <= object.ZopeTime()"
-             )
-}
-
-_WF_WORKLISTS = \
-{ 'expired_list':   ( 'Expired'
-                    , 'Worklist for expired content'
-                    , { 'state' : ( 'expired', ) }
-                    , 'Expired items'
-                    , 'string:${portal_url}/expired_items'
-                    , 'workflow'
-                    , ( 'Restore expired content', )
-                    , ()
-                    , ()
-                    , ""
-                    )
-, 'alive_list':     ( 'Alive'
-                    , 'Worklist for content not yet expired / killed'
-                    , { 'state' : ( 'open',  'closed' ) }
-                    , 'Expired items'
-                    , 'string:${portal_url}/expired_items'
-                    , 'workflow'
-                    , ( 'Restore expired content', )
-                    , ()
-                    , ()
-                    , ""
-                    )
-}
-
-_BEFORE_OPEN_SCRIPT = """\
-## Script (Python) "before_open"
-##bind container=container
-##bind context=context
-##bind namespace=
-##bind script=script
-##bind subpath=traverse_subpath
-##parameters=
-##title=
-##
-return 'before_open'
-"""
-
-_AFTER_CLOSE_SCRIPT = """\
-## Script (Python) "after_close"
-##bind container=container
-##bind context=context
-##bind namespace=
-##bind script=script
-##bind subpath=traverse_subpath
-##parameters=
-##title=
-##
-return 'after_close'
-"""
-
-_AFTER_KILL_SCRIPT = """\
-## Script (Python) "after_kill"
-##bind container=container
-##bind context=context
-##bind namespace=
-##bind script=script
-##bind subpath=traverse_subpath
-##parameters=
-##title=
-##
-return 'after_kill'
-"""
-
-_WF_SCRIPTS = \
-{ 'before_open':    ( PythonScript.meta_type
-                    , _BEFORE_OPEN_SCRIPT
-                    , 'workflows/%s/scripts/before_open.py'
-                    , None
-                    , None
-                    )
-, 'after_close':    ( PythonScript.meta_type
-                    , _AFTER_CLOSE_SCRIPT
-                    , 'workflows/%s/scripts/after_close.py'
-                    , None
-                    , None
-                    )
-, 'after_kill':     ( PythonScript.meta_type
-                    , _AFTER_KILL_SCRIPT
-                    , 'workflows/%s/scripts/after_kill.py'
-                    , None
-                    , None
-                    )
-, 'before_expire': ( ExternalMethod.meta_type
-                   , ''
-                   , ''
-                   , 'CMFSetup.test_method'
-                   , 'test'
-                   )
-}
-
-_EMPTY_TOOL_EXPORT = """\
-<?xml version="1.0"?>
-<workflow-tool>
- <bindings>
-  <default>
-  </default>
- </bindings>
-</workflow-tool>
-"""
-
-_BINDINGS_TOOL_EXPORT = """\
-<?xml version="1.0"?>
-<workflow-tool>
- <bindings>
-  <default>
-   <bound-workflow workflow_id="non_dcworkflow_0" />
-   <bound-workflow workflow_id="non_dcworkflow_1" />
-  </default>
-  <type type_id="sometype">
-   <bound-workflow workflow_id="non_dcworkflow_2" />
-  </type>
-  <type type_id="anothertype">
-   <bound-workflow workflow_id="non_dcworkflow_3" />
-  </type>
- </bindings>
-</workflow-tool>
-"""
-
-_OVERRIDE_TOOL_EXPORT = """\
-<?xml version="1.0"?>
-<workflow-tool>
- <bindings>
-  <default>
-   <bound-workflow workflow_id="foo" />
-   <bound-workflow workflow_id="bar" />
-  </default>
-  <type type_id="qux">
-   <bound-workflow workflow_id="baz" />
-  </type>
- </bindings>
-</workflow-tool>
-"""
-
-_NORMAL_TOOL_EXPORT = """\
-<?xml version="1.0"?>
-<workflow-tool>
- <workflow
-    workflow_id="non_dcworkflow"
-    meta_type="Dummy Workflow"
-    />
- <workflow
-    workflow_id="dcworkflow"
-    filename="workflows/dcworkflow/definition.xml"
-    meta_type="Workflow"
-    />
- <bindings>
-  <default>
-  </default>
- </bindings>
-</workflow-tool>
-"""
-
-_NORMAL_TOOL_EXPORT_WITH_FILENAME = """\
-<?xml version="1.0"?>
-<workflow-tool>
- <workflow
-    workflow_id="non_dcworkflow"
-    meta_type="Dummy Workflow"
-    />
- <workflow
-    workflow_id="dcworkflow"
-    filename="workflows/%s/definition.xml"
-    meta_type="Workflow"
-    />
- <bindings>
-  <default>
-  </default>
- </bindings>
-</workflow-tool>
-"""
-
-_FILENAME_TOOL_EXPORT = """\
-<?xml version="1.0"?>
-<workflow-tool>
- <workflow
-    workflow_id="name with spaces"
-    filename="workflows/name_with_spaces/definition.xml"
-    meta_type="Workflow"
-    />
- <bindings>
-  <default>
-  </default>
- </bindings>
-</workflow-tool>
-"""
-
-_EMPTY_WORKFLOW_EXPORT = """\
-<?xml version="1.0"?>
-<dc-workflow
-    workflow_id="%s"
-    title="%s"
-    state_variable="state"
-    initial_state="%s">
-</dc-workflow>
-"""
-
-# Make sure old exports are still imported well. Changes:
-# - scripts are now in in a 'scripts' subdirectory
-_OLD_WORKFLOW_EXPORT = """\
-<?xml version="1.0"?>
-<dc-workflow
-    workflow_id="%(workflow_id)s"
-    title="%(title)s"
-    state_variable="state"
-    initial_state="%(initial_state)s">
- <permission>Open content for modifications</permission>
- <permission>Modify content</permission>
- <permission>Query history</permission>
- <permission>Restore expired content</permission>
- <state
-    state_id="closed"
-    title="Closed">
-  <description>Closed for modifications</description>
-  <exit-transition
-    transition_id="open"/>
-  <exit-transition
-    transition_id="kill"/>
-  <exit-transition
-    transition_id="expire"/>
-  <permission-map
-    acquired="False"
-    name="Modify content">
-  </permission-map>
-  <assignment
-    name="is_closed"
-    type="bool">True</assignment>
-  <assignment
-    name="is_opened"
-    type="bool">False</assignment>
- </state>
- <state
-    state_id="expired"
-    title="Expired">
-  <description>Expiration date has passed</description>
-  <exit-transition
-    transition_id="open"/>
-  <permission-map
-    acquired="True"
-    name="Modify content">
-   <permission-role>Owner</permission-role>
-   <permission-role>Manager</permission-role>
-  </permission-map>
-  <assignment
-    name="is_closed"
-    type="bool">False</assignment>
-  <assignment
-    name="is_opened"
-    type="bool">False</assignment>
- </state>
- <state
-    state_id="killed"
-    title="Killed">
-  <description>Permanently unavailable</description>
- </state>
- <state
-    state_id="opened"
-    title="Opened">
-  <description>Open for modifications</description>
-  <exit-transition
-    transition_id="close"/>
-  <exit-transition
-    transition_id="kill"/>
-  <exit-transition
-    transition_id="expire"/>
-  <permission-map
-    acquired="True"
-    name="Modify content">
-   <permission-role>Owner</permission-role>
-   <permission-role>Manager</permission-role>
-  </permission-map>
-  <group-map name="Content_owners">
-   <group-role>Owner</group-role>
-  </group-map>
-  <assignment
-    name="is_closed"
-    type="bool">False</assignment>
-  <assignment
-    name="is_opened"
-    type="bool">True</assignment>
- </state>
- <transition
-    transition_id="close"
-    title="Close"
-    trigger="USER"
-    new_state="closed"
-    before_script=""
-    after_script="after_close">
-  <description>Close the object for modifications</description>
-  <action
-    category="workflow"
-    url="string:${object_url}/close_for_modifications">Close</action>
-  <guard>
-   <guard-role>Owner</guard-role>
-   <guard-role>Manager</guard-role>
-  </guard>
- </transition>
- <transition
-    transition_id="expire"
-    title="Expire"
-    trigger="AUTOMATIC"
-    new_state="expired"
-    before_script="before_expire"
-    after_script="">
-  <description>Retire objects whose expiration is past.</description>
-  <guard>
-   <guard-expression>python: object.expiration() &lt;= object.ZopeTime()</guard-expression>
-  </guard>
-  <assignment
-    name="when_expired">object/ZopeTime</assignment>
- </transition>
- <transition
-    transition_id="kill"
-    title="Kill"
-    trigger="USER"
-    new_state="killed"
-    before_script=""
-    after_script="after_kill">
-  <description>Make the object permanently unavailable.</description>
-  <action
-    category="workflow"
-    url="string:${object_url}/kill_object">Kill</action>
-  <guard>
-   <guard-group>Content_assassins</guard-group>
-  </guard>
-  <assignment
-    name="killed_by">string:${user/getId}</assignment>
- </transition>
- <transition
-    transition_id="open"
-    title="Open"
-    trigger="USER"
-    new_state="opened"
-    before_script="before_open"
-    after_script="">
-  <description>Open the object for modifications</description>
-  <action
-    category="workflow"
-    url="string:${object_url}/open_for_modifications">Open</action>
-  <guard>
-   <guard-permission>Open content for modifications</guard-permission>
-  </guard>
-  <assignment
-    name="when_opened">object/ZopeTime</assignment>
- </transition>
- <worklist
-    worklist_id="alive_list"
-    title="Alive">
-  <description>Worklist for content not yet expired / killed</description>
-  <action
-    category="workflow"
-    url="string:${portal_url}/expired_items">Expired items</action>
-  <guard>
-   <guard-permission>Restore expired content</guard-permission>
-  </guard>
-  <match name="state" values="open; closed"/>
- </worklist>
- <worklist
-    worklist_id="expired_list"
-    title="Expired">
-  <description>Worklist for expired content</description>
-  <action
-    category="workflow"
-    url="string:${portal_url}/expired_items">Expired items</action>
-  <guard>
-   <guard-permission>Restore expired content</guard-permission>
-  </guard>
-  <match name="state" values="expired"/>
- </worklist>
- <variable
-    variable_id="killed_by"
-    for_catalog="True"
-    for_status="False"
-    update_always="True">
-   <description>Killed by</description>
-   <default>
-    <value type="string">n/a</value>
-   </default>
-   <guard>
-    <guard-role>Hangman</guard-role>
-    <guard-role>Sherrif</guard-role>
-   </guard>
- </variable>
- <variable
-    variable_id="when_expired"
-    for_catalog="True"
-    for_status="False"
-    update_always="True">
-   <description>Expired when</description>
-   <default>
-    <expression>nothing</expression>
-   </default>
-   <guard>
-    <guard-permission>Query history</guard-permission>
-    <guard-permission>Open content for modifications</guard-permission>
-   </guard>
- </variable>
- <variable
-    variable_id="when_opened"
-    for_catalog="True"
-    for_status="False"
-    update_always="True">
-   <description>Opened when</description>
-   <default>
-    <expression>python:None</expression>
-   </default>
-   <guard>
-    <guard-permission>Query history</guard-permission>
-    <guard-permission>Open content for modifications</guard-permission>
-   </guard>
- </variable>
- <script
-    script_id="after_close"
-    type="Script (Python)"
-    filename="workflows/%(workflow_filename)s/after_close.py"
-    module=""
-    function=""
-    />
- <script
-    script_id="after_kill"
-    type="Script (Python)"
-    filename="workflows/%(workflow_filename)s/after_kill.py"
-    module=""
-    function=""
-    />
- <script
-    script_id="before_expire"
-    type="External Method"
-    filename=""
-    module="CMFSetup.test_method"
-    function="test"
-    />
- <script
-    script_id="before_open"
-    type="Script (Python)"
-    filename="workflows/%(workflow_filename)s/before_open.py"
-    module=""
-    function=""
-    />
-</dc-workflow>
-"""
-
-_NORMAL_WORKFLOW_EXPORT = """\
-<?xml version="1.0"?>
-<dc-workflow
-    workflow_id="%(workflow_id)s"
-    title="%(title)s"
-    state_variable="state"
-    initial_state="%(initial_state)s">
- <permission>Open content for modifications</permission>
- <permission>Modify content</permission>
- <permission>Query history</permission>
- <permission>Restore expired content</permission>
- <state
-    state_id="closed"
-    title="Closed">
-  <description>Closed for modifications</description>
-  <exit-transition
-    transition_id="open"/>
-  <exit-transition
-    transition_id="kill"/>
-  <exit-transition
-    transition_id="expire"/>
-  <permission-map
-    acquired="False"
-    name="Modify content">
-  </permission-map>
-  <assignment
-    name="is_closed"
-    type="bool">True</assignment>
-  <assignment
-    name="is_opened"
-    type="bool">False</assignment>
- </state>
- <state
-    state_id="expired"
-    title="Expired">
-  <description>Expiration date has passed</description>
-  <exit-transition
-    transition_id="open"/>
-  <permission-map
-    acquired="True"
-    name="Modify content">
-   <permission-role>Owner</permission-role>
-   <permission-role>Manager</permission-role>
-  </permission-map>
-  <assignment
-    name="is_closed"
-    type="bool">False</assignment>
-  <assignment
-    name="is_opened"
-    type="bool">False</assignment>
- </state>
- <state
-    state_id="killed"
-    title="Killed">
-  <description>Permanently unavailable</description>
- </state>
- <state
-    state_id="opened"
-    title="Opened">
-  <description>Open for modifications</description>
-  <exit-transition
-    transition_id="close"/>
-  <exit-transition
-    transition_id="kill"/>
-  <exit-transition
-    transition_id="expire"/>
-  <permission-map
-    acquired="True"
-    name="Modify content">
-   <permission-role>Owner</permission-role>
-   <permission-role>Manager</permission-role>
-  </permission-map>
-  <group-map name="Content_owners">
-   <group-role>Owner</group-role>
-  </group-map>
-  <assignment
-    name="is_closed"
-    type="bool">False</assignment>
-  <assignment
-    name="is_opened"
-    type="bool">True</assignment>
- </state>
- <transition
-    transition_id="close"
-    title="Close"
-    trigger="USER"
-    new_state="closed"
-    before_script=""
-    after_script="after_close">
-  <description>Close the object for modifications</description>
-  <action
-    category="workflow"
-    url="string:${object_url}/close_for_modifications">Close</action>
-  <guard>
-   <guard-role>Owner</guard-role>
-   <guard-role>Manager</guard-role>
-  </guard>
- </transition>
- <transition
-    transition_id="expire"
-    title="Expire"
-    trigger="AUTOMATIC"
-    new_state="expired"
-    before_script="before_expire"
-    after_script="">
-  <description>Retire objects whose expiration is past.</description>
-  <guard>
-   <guard-expression>python: object.expiration() &lt;= object.ZopeTime()</guard-expression>
-  </guard>
-  <assignment
-    name="when_expired">object/ZopeTime</assignment>
- </transition>
- <transition
-    transition_id="kill"
-    title="Kill"
-    trigger="USER"
-    new_state="killed"
-    before_script=""
-    after_script="after_kill">
-  <description>Make the object permanently unavailable.</description>
-  <action
-    category="workflow"
-    url="string:${object_url}/kill_object">Kill</action>
-  <guard>
-   <guard-group>Content_assassins</guard-group>
-  </guard>
-  <assignment
-    name="killed_by">string:${user/getId}</assignment>
- </transition>
- <transition
-    transition_id="open"
-    title="Open"
-    trigger="USER"
-    new_state="opened"
-    before_script="before_open"
-    after_script="">
-  <description>Open the object for modifications</description>
-  <action
-    category="workflow"
-    url="string:${object_url}/open_for_modifications">Open</action>
-  <guard>
-   <guard-permission>Open content for modifications</guard-permission>
-  </guard>
-  <assignment
-    name="when_opened">object/ZopeTime</assignment>
- </transition>
- <worklist
-    worklist_id="alive_list"
-    title="Alive">
-  <description>Worklist for content not yet expired / killed</description>
-  <action
-    category="workflow"
-    url="string:${portal_url}/expired_items">Expired items</action>
-  <guard>
-   <guard-permission>Restore expired content</guard-permission>
-  </guard>
-  <match name="state" values="open; closed"/>
- </worklist>
- <worklist
-    worklist_id="expired_list"
-    title="Expired">
-  <description>Worklist for expired content</description>
-  <action
-    category="workflow"
-    url="string:${portal_url}/expired_items">Expired items</action>
-  <guard>
-   <guard-permission>Restore expired content</guard-permission>
-  </guard>
-  <match name="state" values="expired"/>
- </worklist>
- <variable
-    variable_id="killed_by"
-    for_catalog="True"
-    for_status="False"
-    update_always="True">
-   <description>Killed by</description>
-   <default>
-    <value type="string">n/a</value>
-   </default>
-   <guard>
-    <guard-role>Hangman</guard-role>
-    <guard-role>Sherrif</guard-role>
-   </guard>
- </variable>
- <variable
-    variable_id="when_expired"
-    for_catalog="True"
-    for_status="False"
-    update_always="True">
-   <description>Expired when</description>
-   <default>
-    <expression>nothing</expression>
-   </default>
-   <guard>
-    <guard-permission>Query history</guard-permission>
-    <guard-permission>Open content for modifications</guard-permission>
-   </guard>
- </variable>
- <variable
-    variable_id="when_opened"
-    for_catalog="True"
-    for_status="False"
-    update_always="True">
-   <description>Opened when</description>
-   <default>
-    <expression>python:None</expression>
-   </default>
-   <guard>
-    <guard-permission>Query history</guard-permission>
-    <guard-permission>Open content for modifications</guard-permission>
-   </guard>
- </variable>
- <script
-    script_id="after_close"
-    type="Script (Python)"
-    filename="workflows/%(workflow_filename)s/scripts/after_close.py"
-    module=""
-    function=""
-    />
- <script
-    script_id="after_kill"
-    type="Script (Python)"
-    filename="workflows/%(workflow_filename)s/scripts/after_kill.py"
-    module=""
-    function=""
-    />
- <script
-    script_id="before_expire"
-    type="External Method"
-    filename=""
-    module="CMFSetup.test_method"
-    function="test"
-    />
- <script
-    script_id="before_open"
-    type="Script (Python)"
-    filename="workflows/%(workflow_filename)s/scripts/before_open.py"
-    module=""
-    function=""
-    />
-</dc-workflow>
-"""
-
-class Test_exportWorkflow( _WorkflowSetup
-                         , _GuardChecker
-                         ):
-
-    def test_empty( self ):
-
-        site = self._initSite()
-        context = DummyExportContext( site )
-
-        from Products.CMFSetup.workflow import exportWorkflowTool
-        exportWorkflowTool( context )
-
-        self.assertEqual( len( context._wrote ), 1 )
-        filename, text, content_type = context._wrote[ 0 ]
-        self.assertEqual( filename, 'workflows.xml' )
-        self._compareDOM( text, _EMPTY_TOOL_EXPORT )
-        self.assertEqual( content_type, 'text/xml' )
-
-    def test_normal( self ):
-
-        WF_ID_NON = 'non_dcworkflow'
-        WF_TITLE_NON = 'Non-DCWorkflow'
-        WF_ID_DC = 'dcworkflow'
-        WF_TITLE_DC = 'DCWorkflow'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-
-        wf_tool = site.portal_workflow
-        nondcworkflow = DummyWorkflow( WF_TITLE_NON )
-        nondcworkflow.title = WF_TITLE_NON
-        wf_tool._setObject( WF_ID_NON, nondcworkflow )
-
-        dcworkflow = self._initDCWorkflow( WF_ID_DC )
-        dcworkflow.title = WF_TITLE_DC
-        dcworkflow.initial_state = WF_INITIAL_STATE
-        dcworkflow.permissions = _WF_PERMISSIONS
-        self._initVariables( dcworkflow )
-        self._initStates( dcworkflow )
-        self._initTransitions( dcworkflow )
-        self._initWorklists( dcworkflow )
-        self._initScripts( dcworkflow )
-
-        context = DummyExportContext( site )
-
-        from Products.CMFSetup.workflow import exportWorkflowTool
-        exportWorkflowTool( context )
-
-        # workflows list, wf defintion and 3 scripts
-        self.assertEqual( len( context._wrote ), 5 )
-
-        filename, text, content_type = context._wrote[ 0 ]
-        self.assertEqual( filename, 'workflows.xml' )
-        self._compareDOM( text, _NORMAL_TOOL_EXPORT )
-        self.assertEqual( content_type, 'text/xml' )
-
-        filename, text, content_type = context._wrote[ 1 ]
-        self.assertEqual( filename, 'workflows/%s/definition.xml' % WF_ID_DC )
-        self._compareDOM( text
-                        , _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID_DC
-                            , 'title' : WF_TITLE_DC
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID_DC.replace(' ', '_')
-                            } )
-        self.assertEqual( content_type, 'text/xml' )
-
-        # just testing first script
-        filename, text, content_type = context._wrote[ 2 ]
-        self.assertEqual( filename, 'workflows/%s/scripts/after_close.py' % WF_ID_DC )
-        self.assertEqual( text, _AFTER_CLOSE_SCRIPT)
-        self.assertEqual( content_type, 'text/plain' )
-
-    def test_with_filenames( self ):
-
-        WF_ID_DC = 'name with spaces'
-        WF_TITLE_DC = 'DCWorkflow with spaces'
-        WF_INITIAL_STATE = 'closed'
-
-        site = self._initSite()
-
-        dcworkflow = self._initDCWorkflow( WF_ID_DC )
-        dcworkflow.title = WF_TITLE_DC
-        dcworkflow.initial_state = WF_INITIAL_STATE
-        dcworkflow.permissions = _WF_PERMISSIONS
-        self._initVariables( dcworkflow )
-        self._initStates( dcworkflow )
-        self._initTransitions( dcworkflow )
-        self._initWorklists( dcworkflow )
-        self._initScripts( dcworkflow )
-
-        context = DummyExportContext( site )
-
-        from Products.CMFSetup.workflow import exportWorkflowTool
-        exportWorkflowTool( context )
-
-        # workflows list, wf defintion and 3 scripts
-        self.assertEqual( len( context._wrote ), 5 )
-
-        filename, text, content_type = context._wrote[ 0 ]
-        self.assertEqual( filename, 'workflows.xml' )
-        self._compareDOM( text, _FILENAME_TOOL_EXPORT )
-        self.assertEqual( content_type, 'text/xml' )
-
-        filename, text, content_type = context._wrote[ 1 ]
-        self.assertEqual( filename
-                        , 'workflows/name_with_spaces/definition.xml' )
-        self._compareDOM( text
-                        , _NORMAL_WORKFLOW_EXPORT
-                          % { 'workflow_id' : WF_ID_DC
-                            , 'title' : WF_TITLE_DC
-                            , 'initial_state' : WF_INITIAL_STATE
-                            , 'workflow_filename' : WF_ID_DC.replace(' ', '_')
-                            } )
-        self.assertEqual( content_type, 'text/xml' )
-
-        # just testing first script
-        filename, text, content_type = context._wrote[ 2 ]
-        self.assertEqual( filename, 'workflows/%s/scripts/after_close.py' %
-                          WF_ID_DC.replace(' ', '_'))
-        self.assertEqual( text, _AFTER_CLOSE_SCRIPT)
-        self.assertEqual( content_type, 'text/plain' )
-
-class Test_importWorkflow( _WorkflowSetup
-                         , _GuardChecker
-                         ):
-
-    def _importNormalWorkflow( self, wf_id, wf_title, wf_initial_state ):
-
-        site = self._initSite()
-        wf_tool = site.portal_workflow
-        workflow_filename = wf_id.replace(' ', '_')
-
-        context = DummyImportContext( site )
-        context._files[ 'workflows.xml'
-                      ] = _NORMAL_TOOL_EXPORT_WITH_FILENAME % workflow_filename
-
-        context._files[ 'workflows/%s/definition.xml' % wf_id
-                      ] = ( _NORMAL_WORKFLOW_EXPORT
-                            % { 'workflow_id' : wf_id
-                              , 'title' : wf_title
-                              , 'initial_state' : wf_initial_state
-                              , 'workflow_filename' : workflow_filename
-                              }
-                          )
-
-        context._files[ 'workflows/%s/scripts/after_close.py' % workflow_filename
-                      ] = _AFTER_CLOSE_SCRIPT
-
-        context._files[ 'workflows/%s/scripts/after_kill.py' % workflow_filename
-                      ] = _AFTER_KILL_SCRIPT
-
-        context._files[ 'workflows/%s/scripts/before_open.py' % workflow_filename
-                      ] = _BEFORE_OPEN_SCRIPT
-
-        from Products.CMFSetup.workflow import importWorkflowTool
-        importWorkflowTool( context )
-
-        return wf_tool
-
-    def _importOldWorkflow( self, wf_id, wf_title, wf_initial_state ):
-
-        site = self._initSite()
-        wf_tool = site.portal_workflow
-        workflow_filename = wf_id.replace(' ', '_')
-
-        context = DummyImportContext( site )
-        context._files[ 'workflows.xml'
-                      ] = _NORMAL_TOOL_EXPORT_WITH_FILENAME % workflow_filename
-
-        context._files[ 'workflows/%s/definition.xml' % wf_id
-                      ] = ( _OLD_WORKFLOW_EXPORT
-                            % { 'workflow_id' : wf_id
-                              , 'title' : wf_title
-                              , 'initial_state' : wf_initial_state
-                              , 'workflow_filename' : workflow_filename
-                              }
-                          )
-
-        context._files[ 'workflows/%s/after_close.py' % workflow_filename
-                      ] = _AFTER_CLOSE_SCRIPT
-
-        context._files[ 'workflows/%s/after_kill.py' % workflow_filename
-                      ] = _AFTER_KILL_SCRIPT
-
-        context._files[ 'workflows/%s/before_open.py' % workflow_filename
-                      ] = _BEFORE_OPEN_SCRIPT
-
-        from Products.CMFSetup.workflow import importWorkflowTool
-        importWorkflowTool( context )
-
-        return wf_tool
-
-    def test_empty_default_purge( self ):
-
-        WF_ID_NON = 'non_dcworkflow_%s'
-        WF_TITLE_NON = 'Non-DCWorkflow #%s'
-
-        site = self._initSite()
-        wf_tool = site.portal_workflow
-
-        for i in range( 4 ):
-            nondcworkflow = DummyWorkflow( WF_TITLE_NON % i )
-            nondcworkflow.title = WF_TITLE_NON % i
-            wf_tool._setObject( WF_ID_NON % i, nondcworkflow )
-
-        wf_tool._default_chain = ( WF_ID_NON % 1, )
-        wf_tool._chains_by_type[ 'sometype' ] = ( WF_ID_NON % 2, )
-        self.assertEqual( len( wf_tool.objectIds() ), 4 )
-
-        context = DummyImportContext( site )
-        context._files[ 'workflows.xml' ] = _EMPTY_TOOL_EXPORT
-
-        from Products.CMFSetup.workflow import importWorkflowTool
-        importWorkflowTool( context )
-
-        self.assertEqual( len( wf_tool.objectIds() ), 0 )
-        self.assertEqual( len( wf_tool._default_chain ), 0 )
-        self.assertEqual( len( wf_tool._chains_by_type ), 0 )
-
-    def test_empty_explicit_purge( self ):
-
-        WF_ID_NON = 'non_dcworkflow_%s'
-        WF_TITLE_NON = 'Non-DCWorkflow #%s'
-
-        site = self._initSite()
-        wf_tool = site.portal_workflow
-
-        for i in range( 4 ):
-            nondcworkflow = DummyWorkflow( WF_TITLE_NON % i )
-            nondcworkflow.title = WF_TITLE_NON % i
-            wf_tool._setObject( WF_ID_NON % i, nondcworkflow )
-
-        wf_tool._default_chain = ( WF_ID_NON % 1, )
-        wf_tool._chains_by_type[ 'sometype' ] = ( WF_ID_NON % 2, )
-        self.assertEqual( len( wf_tool.objectIds() ), 4 )
-
-        context = DummyImportContext( site, True )
-        context._files[ 'workflows.xml' ] = _EMPTY_TOOL_EXPORT
-
-        from Products.CMFSetup.workflow import importWorkflowTool
-        importWorkflowTool( context )
-
-        self.assertEqual( len( wf_tool.objectIds() ), 0 )
-        self.assertEqual( len( wf_tool._default_chain ), 0 )
-        self.assertEqual( len( wf_tool._chains_by_type ), 0 )
-
-    def test_empty_skip_purge( self ):
-
-        WF_ID_NON = 'non_dcworkflow_%s'
-        WF_TITLE_NON = 'Non-DCWorkflow #%s'
-
-        site = self._initSite()
-        wf_tool = site.portal_workflow
-
-        for i in range( 4 ):
-            nondcworkflow = DummyWorkflow( WF_TITLE_NON % i )
-            nondcworkflow.title = WF_TITLE_NON % i
-            wf_tool._setObject( WF_ID_NON % i, nondcworkflow )
-
-        wf_tool._default_chain = ( WF_ID_NON % 1, )
-        wf_tool._chains_by_type[ 'sometype' ] = ( WF_ID_NON % 2, )
-        self.assertEqual( len( wf_tool.objectIds() ), 4 )
-
-        context = DummyImportContext( site, False )
-        context._files[ 'typestool.xml' ] = _EMPTY_TOOL_EXPORT
-
-        from Products.CMFSetup.workflow import importWorkflowTool
-        importWorkflowTool( context )
-
-        self.assertEqual( len( wf_tool.objectIds() ), 4 )
-        self.assertEqual( len( wf_tool._default_chain ), 1 )
-        self.assertEqual( wf_tool._default_chain[ 0 ], WF_ID_NON % 1 )
-        self.assertEqual( len( wf_tool._chains_by_type ), 1 )
-        self.assertEqual( wf_tool._chains_by_type[ 'sometype' ]
-                        , ( WF_ID_NON % 2, )
-                        )
-
-    def test_bindings_skip_purge( self ):
-
-        WF_ID_NON = 'non_dcworkflow_%s'
-        WF_TITLE_NON = 'Non-DCWorkflow #%s'
-
-        site = self._initSite()
-        wf_tool = site.portal_workflow
-
-        for i in range( 4 ):
-            nondcworkflow = DummyWorkflow( WF_TITLE_NON % i )
-            nondcworkflow.title = WF_TITLE_NON % i
-            wf_tool._setObject( WF_ID_NON % i, nondcworkflow )
-
-        wf_tool._default_chain = ( WF_ID_NON % 1, )
-        wf_tool._chains_by_type[ 'sometype' ] = ( WF_ID_NON % 2, )
-        self.assertEqual( len( wf_tool.objectIds() ), 4 )
-
-        context = DummyImportContext( site, False )
-        context._files[ 'workflows.xml' ] = _BINDINGS_TOOL_EXPORT
-
-        from Products.CMFSetup.workflow import importWorkflowTool
-        importWorkflowTool( context )
-
-        self.assertEqual( len( wf_tool.objectIds() ), 4 )
-        self.assertEqual( len( wf_tool._default_chain ), 2 )
-        self.assertEqual( wf_tool._default_chain[ 0 ], WF_ID_NON % 0 )
-        self.assertEqual( wf_tool._default_chain[ 1 ], WF_ID_NON % 1 )
-        self.assertEqual( len( wf_tool._chains_by_type ), 2 )
-        self.assertEqual( wf_tool._chains_by_type[ 'sometype' ]
-                        , ( WF_ID_NON % 2, )
-                        )
-        self.assertEqual( wf_tool._chains_by_type[ 'anothertype' ]
-                        , ( WF_ID_NON % 3, )
-                        )
-
-    def test_from_empty_dcworkflow_top_level( self ):
-
-        WF_ID = 'dcworkflow_tool'
-        WF_TITLE = 'DC Workflow testing tool'
-        WF_INITIAL_STATE = 'closed'
-
-        tool = self._importNormalWorkflow( WF_ID, WF_TITLE, WF_INITIAL_STATE )
-
-        self.assertEqual( len( tool.objectIds() ), 1 )
-        self.assertEqual( tool.objectIds()[ 0 ], WF_ID )
-
-    def test_from_empty_dcworkflow_workflow_attrs( self ):
-
-        WF_ID = 'dcworkflow_attrs'
-        WF_TITLE = 'DC Workflow testing attrs'
-        WF_INITIAL_STATE = 'closed'
-
-        tool = self._importNormalWorkflow( WF_ID, WF_TITLE, WF_INITIAL_STATE )
-
-        workflow = tool.objectValues()[ 0 ]
-        self.assertEqual( workflow.meta_type, DCWorkflowDefinition.meta_type )
-        self.assertEqual( workflow.title, WF_TITLE )
-        self.assertEqual( workflow.state_var, 'state' )
-        self.assertEqual( workflow.initial_state, WF_INITIAL_STATE )
-
-    def test_from_empty_dcworkflow_workflow_permissions( self ):
-
-        WF_ID = 'dcworkflow_permissions'
-        WF_TITLE = 'DC Workflow testing permissions'
-        WF_INITIAL_STATE = 'closed'
-
-        tool = self._importNormalWorkflow( WF_ID, WF_TITLE, WF_INITIAL_STATE )
-
-        workflow = tool.objectValues()[ 0 ]
-
-        permissions = workflow.permissions
-        self.assertEqual( len( permissions ), len( _WF_PERMISSIONS ) )
-
-        for permission in permissions:
-            self.failUnless( permission in _WF_PERMISSIONS )
-
-    def test_from_empty_dcworkflow_workflow_variables( self ):
-
-        WF_ID = 'dcworkflow_variables'
-        WF_TITLE = 'DC Workflow testing variables'
-        WF_INITIAL_STATE = 'closed'
-
-        tool = self._importNormalWorkflow( WF_ID, WF_TITLE, WF_INITIAL_STATE )
-
-        workflow = tool.objectValues()[ 0 ]
-
-        variables = workflow.variables
-
-        self.assertEqual( len( variables.objectItems() )
-                        , len( _WF_VARIABLES ) )
-
-        for id, variable in variables.objectItems():
-
-            expected = _WF_VARIABLES[ variable.getId() ]
-            self.failUnless( expected[ 0 ] in variable.description )
-            self.assertEqual( variable.default_value, expected[ 1 ] )
-            self.assertEqual( variable.getDefaultExprText(), expected[ 2 ] )
-            self.assertEqual( variable.for_catalog, expected[ 3 ] )
-            self.assertEqual( variable.for_status, expected[ 4 ] )
-            self.assertEqual( variable.update_always, expected[ 5 ] )
-
-            guard = variable.getInfoGuard()
-
-            self.assertEqual( guard.permissions, expected[ 6 ] )
-            self.assertEqual( guard.roles, expected[ 7 ] )
-            self.assertEqual( guard.groups, expected[ 8 ] )
-            self.assertEqual( guard.getExprText(), expected[ 9 ] )
-
-    def test_from_empty_dcworkflow_workflow_states( self ):
-
-        WF_ID = 'dcworkflow_states'
-        WF_TITLE = 'DC Workflow testing states'
-        WF_INITIAL_STATE = 'closed'
-
-        tool = self._importNormalWorkflow( WF_ID, WF_TITLE, WF_INITIAL_STATE )
-
-        workflow = tool.objectValues()[ 0 ]
-
-        states = workflow.states
-
-        self.assertEqual( len( states.objectItems() )
-                        , len( _WF_STATES ) )
-
-        for id, state in states.objectItems():
-
-            expected = _WF_STATES[ state.getId() ]
-            self.assertEqual( state.title, expected[ 0 ] )
-            self.failUnless( expected[ 1 ] in state.description )
-
-            self.assertEqual( len( state.transitions ), len( expected[ 2 ] ) )
-
-            for transition_id in state.transitions:
-                self.failUnless( transition_id in expected[ 2 ] )
-
-            for permission in state.getManagedPermissions():
-
-                p_info = state.getPermissionInfo( permission )
-                p_expected = expected[ 3 ].get( permission, [] )
-
-                self.assertEqual( bool( p_info[ 'acquired' ] )
-                                , isinstance(p_expected, list) )
-
-                self.assertEqual( len( p_info[ 'roles' ] ), len( p_expected ) )
-
-                for role in p_info[ 'roles' ]:
-                    self.failIf( role not in p_expected )
-
-            group_roles = state.group_roles or {}
-            self.assertEqual( len( group_roles ), len( expected[ 4 ] ) )
-
-            for group_id, exp_roles in expected[ 4 ]:
-
-                self.assertEqual( len( state.getGroupInfo( group_id ) )
-                                , len( exp_roles ) )
-
-                for role in state.getGroupInfo( group_id ):
-                    self.failUnless( role in exp_roles )
-
-            self.assertEqual( len( state.getVariableValues() )
-                            , len( expected[ 5 ] ) )
-
-            for var_id, value in state.getVariableValues():
-
-                self.assertEqual( value, expected[ 5 ][ var_id ] )
-
-    def test_from_empty_dcworkflow_workflow_transitions( self ):
-
-        WF_ID = 'dcworkflow_transitions'
-        WF_TITLE = 'DC Workflow testing transitions'
-        WF_INITIAL_STATE = 'closed'
-
-        tool = self._importNormalWorkflow( WF_ID, WF_TITLE, WF_INITIAL_STATE )
-
-        workflow = tool.objectValues()[ 0 ]
-
-        transitions = workflow.transitions
-
-        self.assertEqual( len( transitions.objectItems() )
-                        , len( _WF_TRANSITIONS ) )
-
-        for id, transition in transitions.objectItems():
-
-            expected = _WF_TRANSITIONS[ transition.getId() ]
-            self.assertEqual( transition.title, expected[ 0 ] )
-            self.failUnless( expected[ 1 ] in transition.description )
-            self.assertEqual( transition.new_state_id, expected[ 2 ] )
-            self.assertEqual( transition.trigger_type, expected[ 3 ] )
-            self.assertEqual( transition.script_name, expected[ 4 ] )
-            self.assertEqual( transition.after_script_name, expected[ 5 ] )
-            self.assertEqual( transition.actbox_name, expected[ 6 ] )
-            self.assertEqual( transition.actbox_url, expected[ 7 ] )
-            self.assertEqual( transition.actbox_category, expected[ 8 ] )
-
-            var_exprs = transition.var_exprs
-
-            self.assertEqual( len( var_exprs ), len( expected[ 9 ] ) )
-
-            for var_id, expr in var_exprs.items():
-                self.assertEqual( expr, expected[ 9 ][ var_id ] )
-
-            guard = transition.getGuard()
-
-            self.assertEqual( guard.permissions, expected[ 10 ] )
-            self.assertEqual( guard.roles, expected[ 11 ] )
-            self.assertEqual( guard.groups, expected[ 12 ] )
-            self.assertEqual( guard.getExprText(), expected[ 13 ] )
-
-    def test_from_empty_dcworkflow_workflow_worklists( self ):
-
-        WF_ID = 'dcworkflow_worklists'
-        WF_TITLE = 'DC Workflow testing worklists'
-        WF_INITIAL_STATE = 'closed'
-
-        tool = self._importNormalWorkflow( WF_ID, WF_TITLE, WF_INITIAL_STATE )
-
-        workflow = tool.objectValues()[ 0 ]
-
-        worklists = workflow.worklists
-
-        self.assertEqual( len( worklists.objectItems() )
-                        , len( _WF_WORKLISTS ) )
-
-        for id, worklist in worklists.objectItems():
-
-            expected = _WF_WORKLISTS[ worklist.getId() ]
-            self.failUnless( expected[ 1 ] in worklist.description )
-
-            var_matches = worklist.var_matches
-
-            self.assertEqual( len( var_matches ), len( expected[ 2 ] ) )
-
-            for var_id, values in var_matches.items():
-                exp_values = expected[ 2 ][ var_id ]
-                self.assertEqual( len( values ), len( exp_values ) )
-
-                for value in values:
-                    self.failUnless( value in exp_values, values )
-
-            self.assertEqual( worklist.actbox_name, expected[ 3 ] )
-            self.assertEqual( worklist.actbox_url, expected[ 4 ] )
-            self.assertEqual( worklist.actbox_category, expected[ 5 ] )
-
-            guard = worklist.getGuard()
-
-            self.assertEqual( guard.permissions, expected[ 6 ] )
-            self.assertEqual( guard.roles, expected[ 7 ] )
-            self.assertEqual( guard.groups, expected[ 8 ] )
-            self.assertEqual( guard.getExprText(), expected[ 9 ] )
-
-    def test_from_old_dcworkflow_workflow_scripts( self ):
-
-        WF_ID = 'old_dcworkflow_scripts'
-        WF_TITLE = 'Old DC Workflow testing scripts'
-        WF_INITIAL_STATE = 'closed'
-
-        tool = self._importOldWorkflow( WF_ID, WF_TITLE, WF_INITIAL_STATE )
-
-        workflow = tool.objectValues()[ 0 ]
-
-        scripts = workflow.scripts
-
-        self.assertEqual( len( scripts.objectItems() )
-                        , len( _WF_SCRIPTS ) )
-
-        for script_id, script in scripts.objectItems():
-
-            expected = _WF_SCRIPTS[ script_id ]
-
-            self.assertEqual( script.meta_type, expected[ 0 ] )
-
-            if script.meta_type == PythonScript.meta_type:
-                self.assertEqual( script.manage_FTPget(), expected[ 1 ] )
-
-    def test_from_empty_dcworkflow_workflow_scripts( self ):
-
-        WF_ID = 'dcworkflow_scripts'
-        WF_TITLE = 'DC Workflow testing scripts'
-        WF_INITIAL_STATE = 'closed'
-
-        tool = self._importNormalWorkflow( WF_ID, WF_TITLE, WF_INITIAL_STATE )
-
-        workflow = tool.objectValues()[ 0 ]
-
-        scripts = workflow.scripts
-
-        self.assertEqual( len( scripts.objectItems() )
-                        , len( _WF_SCRIPTS ) )
-
-        for script_id, script in scripts.objectItems():
-
-            expected = _WF_SCRIPTS[ script_id ]
-
-            self.assertEqual( script.meta_type, expected[ 0 ] )
-
-            if script.meta_type == PythonScript.meta_type:
-                self.assertEqual( script.manage_FTPget(), expected[ 1 ] )
-
-def test_suite():
-    return unittest.TestSuite((
-        unittest.makeSuite( WorkflowToolConfiguratorTests ),
-        unittest.makeSuite( WorkflowDefinitionConfiguratorTests ),
-        unittest.makeSuite( Test_exportWorkflow ),
-        unittest.makeSuite( Test_importWorkflow ),
-        ))
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')

Modified: CMF/trunk/CMFSetup/utils.py
===================================================================
--- CMF/trunk/CMFSetup/utils.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFSetup/utils.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -352,92 +352,3 @@
         ExportConfiguratorBase.__init__(self, site, encoding)
 
 InitializeClass(ConfiguratorBase)
-
-
-#
-#   deprecated DOM parsing utilities
-#
-_marker = object()
-
-def _queryNodeAttribute( node, attr_name, default, encoding=None ):
-
-    """ Extract a string-valued attribute from node.
-
-    o Return 'default' if the attribute is not present.
-    """
-    attr_node = node.attributes.get( attr_name, _marker )
-
-    if attr_node is _marker:
-        return default
-
-    value = attr_node.nodeValue
-
-    if encoding is not None:
-        value = value.encode( encoding )
-
-    return value
-
-def _getNodeAttribute( node, attr_name, encoding=None ):
-
-    """ Extract a string-valued attribute from node.
-    """
-    value = _queryNodeAttribute( node, attr_name, _marker, encoding )
-
-    if value is _marker:
-        raise ValueError, 'Invalid attribute: %s' % attr_name
-
-    return value
-
-def _queryNodeAttributeBoolean( node, attr_name, default ):
-
-    """ Extract a string-valued attribute from node.
-
-    o Return 'default' if the attribute is not present.
-    """
-    attr_node = node.attributes.get( attr_name, _marker )
-
-    if attr_node is _marker:
-        return default
-
-    value = node.attributes[ attr_name ].nodeValue.lower()
-
-    return value in ( 'true', 'yes', '1' )
-
-def _getNodeAttributeBoolean( node, attr_name ):
-
-    """ Extract a string-valued attribute from node.
-    """
-    value = node.attributes[ attr_name ].nodeValue.lower()
-
-    return value in ( 'true', 'yes', '1' )
-
-def _coalesceTextNodeChildren( node, encoding=None ):
-
-    """ Concatenate all childe text nodes into a single string.
-    """
-    from xml.dom import Node
-    fragments = []
-    node.normalize()
-    child = node.firstChild
-
-    while child is not None:
-
-        if child.nodeType == Node.TEXT_NODE:
-            fragments.append( child.nodeValue )
-
-        child = child.nextSibling
-
-    joined = ''.join( fragments )
-
-    if encoding is not None:
-        joined = joined.encode( encoding )
-
-    return ''.join( [ line.lstrip() for line in joined.splitlines(True) ] )
-
-def _extractDescriptionNode(parent, encoding=None):
-
-    d_nodes = parent.getElementsByTagName('description')
-    if d_nodes:
-        return _coalesceTextNodeChildren(d_nodes[0], encoding)
-    else:
-        return ''

Modified: CMF/trunk/CMFSetup/workflow.py
===================================================================
--- CMF/trunk/CMFSetup/workflow.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFSetup/workflow.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -10,1384 +10,10 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-""" Classes:  WorkflowConfigurator
+"""Workflow tool setup handlers.
 
 $Id$
 """
 
-import re
-from xml.dom.minidom import parseString as domParseString
-
-from AccessControl import ClassSecurityInfo
-from Acquisition import Implicit
-from Globals import InitializeClass
-from Products.PageTemplates.PageTemplateFile import PageTemplateFile
-
-from Products.CMFCore.utils import getToolByName
-from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition
-
-from permissions import ManagePortal
-from utils import _coalesceTextNodeChildren
-from utils import _extractDescriptionNode
-from utils import _getNodeAttribute
-from utils import _getNodeAttributeBoolean
-from utils import _queryNodeAttribute
-from utils import _xmldir
-from utils import ConfiguratorBase
-from utils import CONVERTER, DEFAULT, KEY
-
-
-TRIGGER_TYPES = ( 'AUTOMATIC', 'USER' )
-
-#
-#   Configurator entry points
-#
-_FILENAME = 'workflows.xml'
-
-def importWorkflowTool( context ):
-
-    """ Import worflow tool and contained workflow definitions.
-
-    o 'context' must implement IImportContext.
-
-    o Register via Python:
-
-      registry = site.portal_setup.getImportStepRegistry()
-      registry.registerStep( 'importWorkflowTool'
-                           , '20040602-01'
-                           , Products.CMFSetup.workflow.importWorkflowTool
-                           , ()
-                           , 'Workflow import'
-                           , 'Import worflow tool and contained workflow '
-                             'definitions.'
-                           )
-
-    o Register via XML:
-
-      <setup-step id="importWorkflowTool"
-                  version="20040602-01"
-                  handler="Products.CMFSetup.workflow.importWorkflowTool"
-                  title="Workflow import"
-      >Import worflow tool and contained workflow definitions.</setup-step>
-
-    """
-    site = context.getSite()
-    encoding = context.getEncoding()
-    tool = getToolByName( site, 'portal_workflow' )
-
-    if context.shouldPurge():
-
-        tool.setDefaultChain( '' )
-        if tool._chains_by_type is not None:
-            tool._chains_by_type.clear()
-
-        for workflow_id in tool.getWorkflowIds():
-            tool._delObject( workflow_id )
-
-    text = context.readDataFile( _FILENAME )
-
-    if text is not None:
-
-        wftc = WorkflowToolConfigurator( site, encoding )
-        tool_info = wftc.parseXML( text )
-
-        wfdc = WorkflowDefinitionConfigurator( site )
-
-        for info in tool_info[ 'workflows' ]:
-
-            if info[ 'meta_type' ] == DCWorkflowDefinition.meta_type:
-
-                filename = info[ 'filename' ]
-                sep = filename.rfind( '/' )
-                if sep == -1:
-                    wf_text = context.readDataFile( filename )
-                else:
-                    wf_text = context.readDataFile( filename[sep+1:],
-                                                    filename[:sep] )
-
-                ( workflow_id
-                , title
-                , state_variable
-                , initial_state
-                , states
-                , transitions
-                , variables
-                , worklists
-                , permissions
-                , scripts
-                ) = wfdc.parseWorkflowXML( wf_text, encoding )
-
-                workflow_id = str( workflow_id ) # No unicode!
-
-                tool._setObject( workflow_id
-                               , DCWorkflowDefinition( workflow_id ) )
-
-                workflow = tool._getOb( workflow_id )
-
-                _initDCWorkflow( workflow
-                               , title
-                               , state_variable
-                               , initial_state
-                               , states
-                               , transitions
-                               , variables
-                               , worklists
-                               , permissions
-                               , scripts
-                               , context
-                               )
-            else:
-                pass # TODO: handle non-DCWorkflows
-
-        for type_id, workflow_ids in tool_info[ 'bindings' ].items():
-
-            chain = ','.join( workflow_ids )
-            if type_id is None:
-                tool.setDefaultChain( chain )
-            else:
-                tool.setChainForPortalTypes( ( type_id, ), chain )
-
-    return 'Workflows imported.'
-
-
-def exportWorkflowTool( context ):
-
-    """ Export worflow tool and contained workflow definitions as an XML file.
-
-    o 'context' must implement IExportContext.
-
-    o Register via Python:
-
-      registry = site.portal_setup.getExportStepRegistry()
-      registry.registerStep( 'exportWorkflowTool'
-                           , Products.CMFSetup.workflow.exportWorkflowTool
-                           , 'Workflow export'
-                           , 'Export worflow tool and contained workflow '
-                             'definitions.'
-                           )
-
-    o Register via XML:
-
-      <export-script id="exportWorkflowTool"
-                     version="20040518-01"
-                     handler="Products.CMFSetup.workflow.exportWorkflowTool"
-                     title="Workflow export"
-      >Export worflow tool and contained workflow definitions.</export-script>
-
-    """
-    site = context.getSite()
-    wftc = WorkflowToolConfigurator( site ).__of__( site )
-    wfdc = WorkflowDefinitionConfigurator( site ).__of__( site )
-    wf_tool = getToolByName( site, 'portal_workflow' )
-    text = wftc.generateXML()
-
-    context.writeDataFile( _FILENAME, text, 'text/xml' )
-
-    for wf_id in wf_tool.getWorkflowIds():
-
-        wf_dirname = wf_id.replace( ' ', '_' )
-        wf_xml = wfdc.generateWorkflowXML( wf_id )
-        wf_scripts = wfdc.getWorkflowScripts(wf_id)
-
-        if wf_xml is not None:
-            context.writeDataFile( 'definition.xml'
-                                 , wf_xml
-                                 , 'text/xml'
-                                 , 'workflows/%s' % wf_dirname
-                                 )
-            for script_info in wf_scripts:
-                if script_info['filename']:
-                    context.writeDataFile(script_info['filename'],
-                                          script_info['body'],
-                                          'text/plain')
-
-    return 'Workflows exported.'
-
-
-class WorkflowToolConfigurator(ConfiguratorBase):
-    """ Synthesize XML description of site's workflow tool.
-    """
-    security = ClassSecurityInfo()
-
-    security.declareProtected(ManagePortal, 'getWorkflowInfo')
-    def getWorkflowInfo(self, workflow_id):
-        """ Return a mapping describing a given workflow.
-        """
-        workflow_tool = getToolByName( self._site, 'portal_workflow' )
-        workflow = workflow_tool.getWorkflowById( workflow_id )
-
-        workflow_info = { 'id'          : workflow_id
-                        , 'meta_type'   : workflow.meta_type
-                        , 'title'       : workflow.title_or_id()
-                        }
-
-        if workflow.meta_type == DCWorkflowDefinition.meta_type:
-            workflow_info['filename'] = _getWorkflowFilename(workflow_id)
-
-        return workflow_info
-
-    security.declareProtected( ManagePortal, 'listWorkflowInfo' )
-    def listWorkflowInfo( self ):
-
-        """ Return a sequence of mappings for each workflow in the tool.
-
-        o See 'getWorkflowInfo' for definition of the mappings.
-        """
-        workflow_tool = getToolByName( self._site, 'portal_workflow' )
-        return [ self.getWorkflowInfo( workflow_id )
-                    for workflow_id in workflow_tool.getWorkflowIds() ]
-
-    security.declareProtected( ManagePortal, 'listWorkflowChains' )
-    def listWorkflowChains( self ):
-
-        """ Return a sequence of tuples binding workflows to each content type.
-
-        o Tuples are in the format, '( type_id, [ workflow_id ] )'.
-
-        o The default chain will be first in the list, with None for the
-          'type_id'.
-
-        o The list will only include type-specific chains for types which
-          do not use the default chain.
-        """
-        workflow_tool = getToolByName( self._site, 'portal_workflow' )
-
-        result = [ ( None, workflow_tool._default_chain ) ]
-        if workflow_tool._chains_by_type is None:
-            overrides = []
-        else:
-            overrides = workflow_tool._chains_by_type.items()
-            overrides.sort()
-
-        result.extend( overrides )
-
-        return result
-
-    def _getExportTemplate(self):
-
-        return PageTemplateFile('wtcToolExport.xml', _xmldir)
-
-    def _getImportMapping(self):
-
-        return {
-          'workflow-tool':
-            { 'workflow':       {KEY: 'workflows', DEFAULT: (),
-                                 CONVERTER: self._convertWorkflows},
-              'bindings':       {CONVERTER: self._convertBindings} },
-          'workflow':
-            { 'workflow_id':    {},
-              'meta_type':      {DEFAULT: '%(workflow_id)s'},
-              'filename':       {DEFAULT: '%(workflow_id)s'} },
-          'bindings':
-            { 'default':        {KEY: 'bindings'},
-              'type':           {KEY: 'bindings'} },
-          'default':
-            { 'type_id':        {DEFAULT: None},
-              'bound-workflow': {KEY: 'bound_workflows', DEFAULT: ()} },
-          'type':
-            { 'type_id':        {DEFAULT: None},
-              'bound-workflow': {KEY: 'bound_workflows', DEFAULT: ()} },
-          'bound-workflow':
-            { 'workflow_id':    {KEY: None} } }
-
-    def _convertWorkflows(self, val):
-
-        for wf in val:
-            if wf['meta_type'] == DCWorkflowDefinition.meta_type:
-                if wf['filename'] == wf['workflow_id']:
-                    wf['filename'] = _getWorkflowFilename( wf['filename'] )
-            else:
-                wf['filename'] = None
-
-        return val
-
-    def _convertBindings(self, val):
-
-        result = {}
-
-        for binding in val[0]['bindings']:
-            result[ binding['type_id'] ] = binding['bound_workflows']
-
-        return result
-
-InitializeClass(WorkflowToolConfigurator)
-
-
-class WorkflowDefinitionConfigurator( Implicit ):
-    """ Synthesize XML description of site's workflows.
-    """
-    security = ClassSecurityInfo()
-
-    def __init__( self, site ):
-        self._site = site
-
-    security.declareProtected( ManagePortal, 'getWorkflowInfo' )
-    def getWorkflowInfo( self, workflow_id ):
-
-        """ Return a mapping describing a given workflow.
-
-        o Keys in the mappings:
-
-          'id' -- the ID of the workflow within the tool
-
-          'meta_type' -- the workflow's meta_type
-
-          'title' -- the workflow's title property
-
-        o See '_extractDCWorkflowInfo' below for keys present only for
-          DCWorkflow definitions.
-
-        """
-        workflow_tool = getToolByName( self._site, 'portal_workflow' )
-        workflow = workflow_tool.getWorkflowById( workflow_id )
-
-        workflow_info = { 'id'          : workflow_id
-                        , 'meta_type'   : workflow.meta_type
-                        , 'title'       : workflow.title_or_id()
-                        }
-
-        if workflow.meta_type == DCWorkflowDefinition.meta_type:
-            self._extractDCWorkflowInfo( workflow, workflow_info )
-
-        return workflow_info
-
-
-    security.declareProtected( ManagePortal, 'generateWorkflowXML' )
-    def generateWorkflowXML( self, workflow_id ):
-
-        """ Pseudo API.
-        """
-        info = self.getWorkflowInfo( workflow_id )
-
-        if info[ 'meta_type' ] != DCWorkflowDefinition.meta_type:
-            return None
-
-        return self._workflowConfig( workflow_id=workflow_id )
-
-    security.declareProtected( ManagePortal, 'generateWorkflowScripts' )
-    def getWorkflowScripts( self, workflow_id ):
-        """ Get workflow scripts information
-        """
-        workflow_tool = getToolByName( self._site, 'portal_workflow' )
-        workflow = workflow_tool.getWorkflowById( workflow_id )
-
-        if workflow.meta_type != DCWorkflowDefinition.meta_type:
-            return []
-
-        scripts = self._extractScripts(workflow)
-        return scripts
-
-
-    security.declareProtected( ManagePortal, 'parseWorkflowXML' )
-    def parseWorkflowXML( self, xml, encoding=None ):
-
-        """ Pseudo API.
-        """
-        dom = domParseString( xml )
-
-        root = dom.getElementsByTagName( 'dc-workflow' )[ 0 ]
-
-        workflow_id = _getNodeAttribute( root, 'workflow_id', encoding )
-        title = _getNodeAttribute( root, 'title', encoding )
-        state_variable = _getNodeAttribute( root, 'state_variable', encoding )
-        initial_state = _getNodeAttribute( root, 'initial_state', encoding )
-
-        states = _extractStateNodes( root, encoding )
-        transitions = _extractTransitionNodes( root, encoding )
-        variables = _extractVariableNodes( root, encoding )
-        worklists = _extractWorklistNodes( root, encoding )
-        permissions = _extractPermissionNodes( root, encoding )
-        scripts = _extractScriptNodes( root, encoding )
-
-        return ( workflow_id
-               , title
-               , state_variable
-               , initial_state
-               , states
-               , transitions
-               , variables
-               , worklists
-               , permissions
-               , scripts
-               )
-
-    security.declarePrivate( '_workflowConfig' )
-    _workflowConfig = PageTemplateFile( 'wtcWorkflowExport.xml'
-                                      , _xmldir
-                                      , __name__='workflowConfig'
-                                      )
-
-    security.declarePrivate( '_extractDCWorkflowInfo' )
-    def _extractDCWorkflowInfo( self, workflow, workflow_info ):
-
-        """ Append the information for a 'workflow' into 'workflow_info'
-
-        o 'workflow' must be a DCWorkflowDefinition instance.
-
-        o 'workflow_info' must be a dictionary.
-
-        o The following keys will be added to 'workflow_info':
-
-          'permissions' -- a list of names of permissions managed
-            by the workflow
-
-          'state_variable' -- the name of the workflow's "main"
-            state variable
-
-          'initial_state' -- the name of the state in the workflow
-            in which objects start their lifecycle.
-
-          'variable_info' -- a list of mappings describing the
-            variables tracked by the workflow (see '_extractVariables').
-
-          'state_info' -- a list of mappings describing the
-            states tracked by the workflow (see '_extractStates').
-
-          'transition_info' -- a list of mappings describing the
-            transitions tracked by the workflow (see '_extractTransitions').
-
-          'worklist_info' -- a list of mappings describing the
-            worklists tracked by the workflow (see '_extractWorklists').
-
-          'script_info' -- a list of mappings describing the scripts which
-            provide added business logic (see '_extractScripts').
-        """
-        workflow_info[ 'filename' ] = _getWorkflowFilename( workflow.getId() )
-        workflow_info[ 'state_variable' ] = workflow.state_var
-        workflow_info[ 'initial_state' ] = workflow.initial_state
-        workflow_info[ 'permissions' ] = workflow.permissions
-        workflow_info[ 'variable_info' ] = self._extractVariables( workflow )
-        workflow_info[ 'state_info' ] = self._extractStates( workflow )
-        workflow_info[ 'transition_info' ] = self._extractTransitions(
-                                                                   workflow )
-        workflow_info[ 'worklist_info' ] = self._extractWorklists( workflow )
-        workflow_info[ 'script_info' ] = self._extractScripts( workflow )
-
-    security.declarePrivate( '_extractVariables' )
-    def _extractVariables( self, workflow ):
-
-        """ Return a sequence of mappings describing DCWorkflow variables.
-
-        o Keys for each mapping will include:
-
-          'id' -- the variable's ID
-
-          'description' -- a textual description of the variable
-
-          'for_catalog' -- whether to catalog this variable
-
-          'for_status' -- whether to ??? this variable (XXX)
-
-          'update_always' -- whether to update this variable whenever
-            executing a transition (xxX)
-
-          'default_value' -- a default value for the variable (XXX)
-
-          'default_expression' -- a TALES expression for the default value
-
-          'guard_permissions' -- a list of permissions guarding access
-            to the variable
-
-          'guard_roles' -- a list of roles guarding access
-            to the variable
-
-          'guard_groups' -- a list of groups guarding the transition
-
-          'guard_expr' -- an expression guarding access to the variable
-        """
-        result = []
-
-        items = workflow.variables.objectItems()
-        items.sort()
-
-        for k, v in items:
-
-            guard = v.getInfoGuard()
-
-            default_type = _guessVariableType( v.default_value )
-
-            info = { 'id'                   : k
-                   , 'description'          : v.description
-                   , 'for_catalog'          : bool( v.for_catalog )
-                   , 'for_status'           : bool( v.for_status )
-                   , 'update_always'        : bool( v.update_always )
-                   , 'default_value'        : v.default_value
-                   , 'default_type'         : default_type
-                   , 'default_expr'         : v.getDefaultExprText()
-                   , 'guard_permissions'    : guard.permissions
-                   , 'guard_roles'          : guard.roles
-                   , 'guard_groups'         : guard.groups
-                   , 'guard_expr'           : guard.getExprText()
-                   }
-
-            result.append( info )
-
-        return result
-
-    security.declarePrivate( '_extractStates' )
-    def _extractStates( self, workflow ):
-
-        """ Return a sequence of mappings describing DCWorkflow states.
-
-        o Within the workflow mapping, each 'state_info' mapping has keys:
-
-          'id' -- the state's ID
-
-          'title' -- the state's title
-
-          'description' -- the state's description
-
-          'transitions' -- a list of IDs of transitions out of the state
-
-          'permissions' -- a list of mappings describing the permission
-            map for the state
-
-          'groups' -- a list of ( group_id, (roles,) ) tuples describing the
-            group-role assignments for the state
-
-          'variables' -- a list of mapping for the variables
-            to be set when entering the state.
-
-        o Within the state_info mappings, each 'permissions' mapping
-          has the keys:
-
-          'name' -- the name of the permission
-
-          'roles' -- a sequence of role IDs which have the permission
-
-          'acquired' -- whether roles are acquired for the permission
-
-        o Within the state_info mappings, each 'variable' mapping
-          has the keys:
-
-          'name' -- the name of the variable
-
-          'type' -- the type of the value (allowed values are:
-                    'string', 'datetime', 'bool', 'int')
-
-          'value' -- the value to be set
-        """
-        result = []
-
-        items = workflow.states.objectItems()
-        items.sort()
-
-        for k, v in items:
-
-            groups = v.group_roles and list( v.group_roles.items() ) or []
-            groups = [ x for x in groups if x[1] ]
-            groups.sort()
-
-            variables = list( v.getVariableValues() )
-            variables.sort()
-
-            v_info = []
-
-            for v_name, value in variables:
-                v_info.append( { 'name' : v_name
-                               , 'type' :_guessVariableType( value )
-                               , 'value' : value
-                               } )
-
-            info = { 'id'           : k
-                   , 'title'        : v.title
-                   , 'description'  : v.description
-                   , 'transitions'  : v.transitions
-                   , 'permissions'  : self._extractStatePermissions( v )
-                   , 'groups'       : groups
-                   , 'variables'    : v_info
-                   }
-
-            result.append( info )
-
-        return result
-
-    security.declarePrivate( '_extractStatePermissions' )
-    def _extractStatePermissions( self, state ):
-
-        """ Return a sequence of mappings for the permissions in a state.
-
-        o Each mapping has the keys:
-
-          'name' -- the name of the permission
-
-          'roles' -- a sequence of role IDs which have the permission
-
-          'acquired' -- whether roles are acquired for the permission
-        """
-        result = []
-
-        items = state.permission_roles.items()
-        items.sort()
-
-        for k, v in items:
-
-            result.append( { 'name' : k
-                           , 'roles' : v
-                           , 'acquired' : not isinstance( v, tuple )
-                           } )
-
-        return result
-
-
-    security.declarePrivate( '_extractTransitions' )
-    def _extractTransitions( self, workflow ):
-
-        """ Return a sequence of mappings describing DCWorkflow transitions.
-
-        o Each mapping has the keys:
-
-          'id' -- the transition's ID
-
-          'title' -- the transition's ID
-
-          'description' -- the transition's description
-
-          'new_state_id' -- the ID of the state into which the transition
-            moves an object
-
-          'trigger_type' -- one of the following values, indicating how the
-            transition is fired:
-
-            - "AUTOMATIC" -> fired opportunistically whenever the workflow
-               notices that its guard conditions permit
-
-            - "USER" -> fired in response to user request
-
-          'script_name' -- the ID of a script to be executed before
-             the transition
-
-          'after_script_name' -- the ID of a script to be executed after
-             the transition
-
-          'actbox_name' -- the name of the action by which the user
-             triggers the transition
-
-          'actbox_url' -- the URL of the action by which the user
-             triggers the transition
-
-          'actbox_category' -- the category of the action by which the user
-             triggers the transition
-
-          'variables' -- a list of ( id, expr ) tuples defining how variables
-            are to be set during the transition
-
-          'guard_permissions' -- a list of permissions guarding the transition
-
-          'guard_roles' -- a list of roles guarding the transition
-
-          'guard_groups' -- a list of groups guarding the transition
-
-          'guard_expr' -- an expression guarding the transition
-
-        """
-        result = []
-
-        items = workflow.transitions.objectItems()
-        items.sort()
-
-        for k, v in items:
-
-            guard = v.getGuard()
-
-            v_info = []
-
-            for v_name, expr in v.getVariableExprs():
-                v_info.append( { 'name' : v_name, 'expr' : expr } )
-
-            info = { 'id'                   : k
-                   , 'title'                : v.title
-                   , 'description'          : v.description
-                   , 'new_state_id'         : v.new_state_id
-                   , 'trigger_type'         : TRIGGER_TYPES[ v.trigger_type ]
-                   , 'script_name'          : v.script_name
-                   , 'after_script_name'    : v.after_script_name
-                   , 'actbox_name'          : v.actbox_name
-                   , 'actbox_url'           : v.actbox_url
-                   , 'actbox_category'      : v.actbox_category
-                   , 'variables'            : v_info
-                   , 'guard_permissions'    : guard.permissions
-                   , 'guard_roles'          : guard.roles
-                   , 'guard_groups'         : guard.groups
-                   , 'guard_expr'           : guard.getExprText()
-                   }
-
-            result.append( info )
-
-        return result
-
-    security.declarePrivate( '_extractWorklists' )
-    def _extractWorklists( self, workflow ):
-
-        """ Return a sequence of mappings describing DCWorkflow transitions.
-
-        o Each mapping has the keys:
-
-          'id' -- the ID of the worklist
-
-          'title' -- the title of the worklist
-
-          'description' -- a textual description of the worklist
-
-          'var_match' -- a list of ( key, value ) tuples defining
-            the variables used to "activate" the worklist.
-
-          'actbox_name' -- the name of the "action" corresponding to the
-            worklist
-
-          'actbox_url' -- the URL of the "action" corresponding to the
-            worklist
-
-          'actbox_category' -- the category of the "action" corresponding
-            to the worklist
-
-          'guard_permissions' -- a list of permissions guarding access
-            to the worklist
-
-          'guard_roles' -- a list of roles guarding access
-            to the worklist
-
-          'guard_expr' -- an expression guarding access to the worklist
-
-        """
-        result = []
-
-        items = workflow.worklists.objectItems()
-        items.sort()
-
-        for k, v in items:
-
-            guard = v.getGuard()
-
-            var_match = [ ( id, v.getVarMatchText( id ) )
-                            for id in v.getVarMatchKeys() ]
-
-            info = { 'id'                   : k
-                   , 'title'                : v.title
-                   , 'description'          : v.description
-                   , 'var_match'            : var_match
-                   , 'actbox_name'          : v.actbox_name
-                   , 'actbox_url'           : v.actbox_url
-                   , 'actbox_category'      : v.actbox_category
-                   , 'guard_permissions'    : guard.permissions
-                   , 'guard_roles'          : guard.roles
-                   , 'guard_groups'         : guard.groups
-                   , 'guard_expr'           : guard.getExprText()
-                   }
-
-            result.append( info )
-
-        return result
-
-    security.declarePrivate( '_extractScripts' )
-    def _extractScripts( self, workflow ):
-
-        """ Return a sequence of mappings describing DCWorkflow scripts.
-
-        o Each mapping has the keys:
-
-          'id' -- the ID of the script
-
-          'meta_type' -- the title of the worklist
-
-          'body' -- the text of the script (only applicable to scripts
-            of type Script (Python))
-
-          'module' -- The module from where to load the function (only
-            applicable to External Method scripts)
-
-          'function' -- The function to load from the 'module' given
-            (Only applicable to External Method scripts)
-
-          'filename' -- the name of the file to / from which the script
-            is stored / loaded (Script (Python) only)
-        """
-        result = []
-
-        items = workflow.scripts.objectItems()
-        items.sort()
-
-        for k, v in items:
-
-            filename = _getScriptFilename( workflow.getId(), k, v.meta_type )
-            body = ''
-            module = ''
-            function = ''
-
-            if v.meta_type == 'Script (Python)':
-                body = v.read()
-
-            if v.meta_type == 'External Method':
-                module = v.module()
-                function = v.function()
-
-            info = { 'id'                   : k
-                   , 'meta_type'            : v.meta_type
-                   , 'body'                 : body
-                   , 'module'               : module
-                   , 'function'             : function
-                   , 'filename'             : filename
-                   }
-
-            result.append( info )
-
-        return result
-
-InitializeClass( WorkflowDefinitionConfigurator )
-
-
-def _getWorkflowFilename( workflow_id ):
-
-    """ Return the name of the file which holds info for a given workflow.
-    """
-    return 'workflows/%s/definition.xml' % workflow_id.replace( ' ', '_' )
-
-def _getScriptFilename( workflow_id, script_id, meta_type ):
-
-    """ Return the name of the file which holds the script.
-    """
-    wf_dir = workflow_id.replace( ' ', '_' )
-    suffix = _METATYPE_SUFFIXES.get(meta_type, None)
-
-    if suffix is None:
-        return ''
-
-    return 'workflows/%s/scripts/%s.%s' % ( wf_dir, script_id, suffix )
-
-def _extractStateNodes( root, encoding=None ):
-
-    result = []
-
-    for s_node in root.getElementsByTagName( 'state' ):
-
-        info = { 'state_id' : _getNodeAttribute( s_node, 'state_id', encoding )
-               , 'title' : _getNodeAttribute( s_node, 'title', encoding )
-               , 'description' : _extractDescriptionNode( s_node, encoding )
-               }
-
-        info[ 'transitions' ] = [ _getNodeAttribute( x, 'transition_id'
-                                                   , encoding )
-                                  for x in s_node.getElementsByTagName(
-                                                        'exit-transition' ) ]
-
-        info[ 'permissions' ] = permission_map = {}
-
-        for p_map in s_node.getElementsByTagName( 'permission-map' ):
-
-            name = _getNodeAttribute( p_map, 'name', encoding )
-            acquired = _getNodeAttributeBoolean( p_map, 'acquired' )
-
-            roles = [ _coalesceTextNodeChildren( x, encoding )
-                        for x in p_map.getElementsByTagName(
-                                            'permission-role' ) ]
-
-            if not acquired:
-                roles = tuple( roles )
-
-            permission_map[ name ] = roles
-
-        info[ 'groups' ] = group_map = []
-
-        for g_map in s_node.getElementsByTagName( 'group-map' ):
-
-            name = _getNodeAttribute( g_map, 'name', encoding )
-
-            roles = [ _coalesceTextNodeChildren( x, encoding )
-                        for x in g_map.getElementsByTagName(
-                                            'group-role' ) ]
-
-            group_map.append( ( name, tuple( roles ) ) )
-
-        info[ 'variables' ] = var_map = {}
-
-        for assignment in s_node.getElementsByTagName( 'assignment' ):
-
-            name = _getNodeAttribute( assignment, 'name', encoding )
-            type_id = _getNodeAttribute( assignment, 'type', encoding )
-            value = _coalesceTextNodeChildren( assignment, encoding )
-
-            var_map[ name ] = { 'name'  : name
-                              , 'type'  : type_id
-                              , 'value' : value
-                              }
-
-        result.append( info )
-
-    return result
-
-def _extractTransitionNodes( root, encoding=None ):
-
-    result = []
-
-    for t_node in root.getElementsByTagName( 'transition' ):
-
-        info = { 'transition_id' : _getNodeAttribute( t_node, 'transition_id'
-                                                    , encoding )
-               , 'title' : _getNodeAttribute( t_node, 'title', encoding )
-               , 'description' : _extractDescriptionNode( t_node, encoding )
-               , 'new_state' : _getNodeAttribute( t_node, 'new_state'
-                                                , encoding )
-               , 'trigger' : _getNodeAttribute( t_node, 'trigger', encoding )
-               , 'before_script' : _getNodeAttribute( t_node, 'before_script'
-                                                  , encoding )
-               , 'after_script' : _getNodeAttribute( t_node, 'after_script'
-                                                   , encoding )
-               , 'action' : _extractActionNode( t_node, encoding )
-               , 'guard' : _extractGuardNode( t_node, encoding )
-               }
-
-        info[ 'variables' ] = var_map = {}
-
-        for assignment in t_node.getElementsByTagName( 'assignment' ):
-
-            name = _getNodeAttribute( assignment, 'name', encoding )
-            expr = _coalesceTextNodeChildren( assignment, encoding )
-            var_map[ name ] = expr
-
-        result.append( info )
-
-    return result
-
-def _extractVariableNodes( root, encoding=None ):
-
-    result = []
-
-    for v_node in root.getElementsByTagName( 'variable' ):
-
-        info = { 'variable_id' : _getNodeAttribute( v_node, 'variable_id'
-                                                    , encoding )
-               , 'description' : _extractDescriptionNode( v_node, encoding )
-               , 'for_catalog' : _getNodeAttributeBoolean( v_node
-                                                         , 'for_catalog'
-                                                         )
-               , 'for_status' : _getNodeAttributeBoolean( v_node
-                                                        , 'for_status'
-                                                        )
-               , 'update_always' : _getNodeAttributeBoolean( v_node
-                                                           , 'update_always'
-                                                           )
-               , 'default' : _extractDefaultNode( v_node, encoding )
-               , 'guard' : _extractGuardNode( v_node, encoding )
-               }
-
-        result.append( info )
-
-    return result
-
-def _extractWorklistNodes( root, encoding=None ):
-
-    result = []
-
-    for w_node in root.getElementsByTagName( 'worklist' ):
-
-        info = { 'worklist_id' : _getNodeAttribute( w_node, 'worklist_id'
-                                                    , encoding )
-               , 'title' : _getNodeAttribute( w_node, 'title' , encoding )
-               , 'description' : _extractDescriptionNode( w_node, encoding )
-               , 'match' : _extractMatchNode( w_node, encoding )
-               , 'action' : _extractActionNode( w_node, encoding )
-               , 'guard' : _extractGuardNode( w_node, encoding )
-               }
-
-        result.append( info )
-
-    return result
-
-def _extractScriptNodes( root, encoding=None ):
-
-    result = []
-
-    for s_node in root.getElementsByTagName( 'script' ):
-
-        try:
-            function = _getNodeAttribute( s_node, 'function' )
-        except ValueError:
-            function = ''
-
-        try:
-            module = _getNodeAttribute( s_node, 'module' )
-        except ValueError:
-            module = ''
-
-        info = { 'script_id' : _getNodeAttribute( s_node, 'script_id' )
-               , 'meta_type' : _getNodeAttribute( s_node, 'type' , encoding )
-               , 'function'  : function
-               , 'module'    : module
-               }
-
-        filename = _queryNodeAttribute( s_node, 'filename' , None, encoding )
-
-        if filename is not None:
-            info[ 'filename' ] = filename
-
-        result.append( info )
-
-    return result
-
-def _extractPermissionNodes( root, encoding=None ):
-
-    result = []
-
-    for p_node in root.getElementsByTagName( 'permission' ):
-
-        result.append( _coalesceTextNodeChildren( p_node, encoding ) )
-
-    return result
-
-def _extractActionNode( parent, encoding=None ):
-
-    nodes = parent.getElementsByTagName( 'action' )
-    assert len( nodes ) <= 1, nodes
-
-    if len( nodes ) < 1:
-        return { 'name' : '', 'url' : '', 'category' : '' }
-
-    node = nodes[ 0 ]
-
-    return { 'name' : _coalesceTextNodeChildren( node, encoding )
-           , 'url' : _getNodeAttribute( node, 'url', encoding )
-           , 'category' : _getNodeAttribute( node, 'category', encoding )
-           }
-
-def _extractGuardNode( parent, encoding=None ):
-
-    nodes = parent.getElementsByTagName( 'guard' )
-    assert len( nodes ) <= 1, nodes
-
-    if len( nodes ) < 1:
-        return { 'permissions' : (), 'roles' : (), 'groups' : (), 'expr' : '' }
-
-    node = nodes[ 0 ]
-
-    expr_nodes = node.getElementsByTagName( 'guard-expression' )
-    assert( len( expr_nodes ) <= 1 )
-
-    expr_text = expr_nodes and _coalesceTextNodeChildren( expr_nodes[ 0 ]
-                                                        , encoding
-                                                        ) or ''
-
-    return { 'permissions' : [ _coalesceTextNodeChildren( x, encoding )
-                                for x in node.getElementsByTagName(
-                                                    'guard-permission' ) ]
-           , 'roles' : [ _coalesceTextNodeChildren( x, encoding )
-                          for x in node.getElementsByTagName( 'guard-role' ) ]
-           , 'groups' : [ _coalesceTextNodeChildren( x, encoding )
-                          for x in node.getElementsByTagName( 'guard-group' ) ]
-           , 'expression' : expr_text
-           }
-
-def _extractDefaultNode( parent, encoding=None ):
-
-    nodes = parent.getElementsByTagName( 'default' )
-    assert len( nodes ) <= 1, nodes
-
-    if len( nodes ) < 1:
-        return { 'value' : '', 'expression' : '', 'type' : 'n/a' }
-
-    node = nodes[ 0 ]
-
-    value_nodes = node.getElementsByTagName( 'value' )
-    assert( len( value_nodes ) <= 1 )
-
-    value_type = 'n/a'
-    if value_nodes:
-        value_type = value_nodes[ 0 ].getAttribute( 'type' ) or 'n/a'
-
-    value_text = value_nodes and _coalesceTextNodeChildren( value_nodes[ 0 ]
-                                                          , encoding
-                                                          ) or ''
-
-    expr_nodes = node.getElementsByTagName( 'expression' )
-    assert( len( expr_nodes ) <= 1 )
-
-    expr_text = expr_nodes and _coalesceTextNodeChildren( expr_nodes[ 0 ]
-                                                        , encoding
-                                                        ) or ''
-
-    return { 'value' : value_text
-           , 'type' : value_type
-           , 'expression' : expr_text
-           }
-
-_SEMICOLON_LIST_SPLITTER = re.compile( r';[ ]*' )
-
-def _extractMatchNode( parent, encoding=None ):
-
-    nodes = parent.getElementsByTagName( 'match' )
-
-    result = {}
-
-    for node in nodes:
-
-        name = _getNodeAttribute( node, 'name', encoding )
-        values = _getNodeAttribute( node, 'values', encoding )
-        result[ name ] = _SEMICOLON_LIST_SPLITTER.split( values )
-
-    return result
-
-def _guessVariableType( value ):
-
-    from DateTime.DateTime import DateTime
-
-    if value is None:
-        return 'none'
-
-    if isinstance( value, DateTime ):
-        return 'datetime'
-
-    if isinstance( value, bool ):
-        return 'bool'
-
-    if isinstance( value, int ):
-        return 'int'
-
-    if isinstance( value, float ):
-        return 'float'
-
-    if isinstance( value, basestring ):
-        return 'string'
-
-    return 'unknown'
-
-def _convertVariableValue( value, type_id ):
-
-    from DateTime.DateTime import DateTime
-
-    if type_id == 'none':
-        return None
-
-    if type_id == 'datetime':
-
-        return DateTime( value )
-
-    if type_id == 'bool':
-
-        if isinstance( value, basestring ):
-
-            value = str( value ).lower()
-
-            return value in ( 'true', 'yes', '1' )
-
-        else:
-            return bool( value )
-
-    if type_id == 'int':
-        return int( value )
-
-    if type_id == 'float':
-        return float( value )
-
-    return value
-
-from Products.PythonScripts.PythonScript import PythonScript
-from Products.ExternalMethod.ExternalMethod import ExternalMethod
-from OFS.DTMLMethod import DTMLMethod
-
-_METATYPE_SUFFIXES = \
-{ PythonScript.meta_type : 'py'
-, DTMLMethod.meta_type : 'dtml'
-}
-
-def _initDCWorkflow( workflow
-                   , title
-                   , state_variable
-                   , initial_state
-                   , states
-                   , transitions
-                   , variables
-                   , worklists
-                   , permissions
-                   , scripts
-                   , context
-                   ):
-    """ Initialize a DC Workflow using values parsed from XML.
-    """
-    workflow.title = title
-    workflow.state_var = state_variable
-    workflow.initial_state = initial_state
-
-    permissions = permissions[:]
-    permissions.sort()
-    workflow.permissions = tuple(permissions)
-
-    _initDCWorkflowVariables( workflow, variables )
-    _initDCWorkflowStates( workflow, states )
-    _initDCWorkflowTransitions( workflow, transitions )
-    _initDCWorkflowWorklists( workflow, worklists )
-    _initDCWorkflowScripts( workflow, scripts, context )
-
-
-def _initDCWorkflowVariables( workflow, variables ):
-
-    """ Initialize DCWorkflow variables
-    """
-    from Products.DCWorkflow.Variables import VariableDefinition
-
-    for v_info in variables:
-
-        id = str( v_info[ 'variable_id' ] ) # no unicode!
-        v = VariableDefinition( id )
-        workflow.variables._setObject( id, v )
-        v = workflow.variables._getOb( id )
-
-        guard = v_info[ 'guard' ]
-        props = { 'guard_roles' : ';'.join( guard[ 'roles' ] )
-                , 'guard_permissions' : ';'.join( guard[ 'permissions' ] )
-                , 'guard_groups' : ';'.join( guard[ 'groups' ] )
-                , 'guard_expr' : guard[ 'expression' ]
-                }
-
-        default = v_info[ 'default' ]
-        default_value = _convertVariableValue( default[ 'value' ]
-                                             , default[ 'type' ] )
-
-        v.setProperties( description = v_info[ 'description' ]
-                       , default_value = default_value
-                       , default_expr = default[ 'expression' ]
-                       , for_catalog = v_info[ 'for_catalog' ]
-                       , for_status = v_info[ 'for_status' ]
-                       , update_always = v_info[ 'update_always' ]
-                       , props = props
-                       )
-
-
-def _initDCWorkflowStates( workflow, states ):
-
-    """ Initialize DCWorkflow states
-    """
-    from Globals import PersistentMapping
-    from Products.DCWorkflow.States import StateDefinition
-
-    for s_info in states:
-
-        id = str( s_info[ 'state_id' ] ) # no unicode!
-        s = StateDefinition( id )
-        workflow.states._setObject( id, s )
-        s = workflow.states._getOb( id )
-
-        s.setProperties( title = s_info[ 'title' ]
-                       , description = s_info[ 'description' ]
-                       , transitions = s_info[ 'transitions' ]
-                       )
-
-        for k, v in s_info[ 'permissions' ].items():
-            s.setPermission( k, isinstance(v, list), v )
-
-        gmap = s.group_roles = PersistentMapping()
-
-        for group_id, roles in s_info[ 'groups' ]:
-            gmap[ group_id ] = roles
-
-        vmap = s.var_values = PersistentMapping()
-
-        for name, v_info in s_info[ 'variables' ].items():
-
-            value = _convertVariableValue( v_info[ 'value' ]
-                                         , v_info[ 'type' ] )
-
-            vmap[ name ] = value
-
-
-def _initDCWorkflowTransitions( workflow, transitions ):
-
-    """ Initialize DCWorkflow transitions
-    """
-    from Globals import PersistentMapping
-    from Products.DCWorkflow.Transitions import TransitionDefinition
-
-    for t_info in transitions:
-
-        id = str( t_info[ 'transition_id' ] ) # no unicode!
-        t = TransitionDefinition( id )
-        workflow.transitions._setObject( id, t )
-        t = workflow.transitions._getOb( id )
-
-        trigger_type = list( TRIGGER_TYPES ).index( t_info[ 'trigger' ] )
-
-        action = t_info[ 'action' ]
-
-        guard = t_info[ 'guard' ]
-        props = { 'guard_roles' : ';'.join( guard[ 'roles' ] )
-                , 'guard_permissions' : ';'.join( guard[ 'permissions' ] )
-                , 'guard_groups' : ';'.join( guard[ 'groups' ] )
-                , 'guard_expr' : guard[ 'expression' ]
-                }
-
-        t.setProperties( title = t_info[ 'title' ]
-                       , description = t_info[ 'description' ]
-                       , new_state_id = t_info[ 'new_state' ]
-                       , trigger_type = trigger_type
-                       , script_name = t_info[ 'before_script' ]
-                       , after_script_name = t_info[ 'after_script' ]
-                       , actbox_name = action[ 'name' ]
-                       , actbox_url = action[ 'url' ]
-                       , actbox_category = action[ 'category' ]
-                       , props = props
-                       )
-
-        t.var_exprs = PersistentMapping( t_info[ 'variables' ].items() )
-
-def _initDCWorkflowWorklists( workflow, worklists ):
-
-    """ Initialize DCWorkflow worklists
-    """
-    from Globals import PersistentMapping
-    from Products.DCWorkflow.Worklists import WorklistDefinition
-
-    for w_info in worklists:
-
-        id = str( w_info[ 'worklist_id' ] ) # no unicode!
-        w = WorklistDefinition( id )
-        workflow.worklists._setObject( id, w )
-
-        w = workflow.worklists._getOb( id )
-
-        action = w_info[ 'action' ]
-
-        guard = w_info[ 'guard' ]
-        props = { 'guard_roles' : ';'.join( guard[ 'roles' ] )
-                , 'guard_permissions' : ';'.join( guard[ 'permissions' ] )
-                , 'guard_groups' : ';'.join( guard[ 'groups' ] )
-                , 'guard_expr' : guard[ 'expression' ]
-                }
-
-        w.setProperties( description = w_info[ 'description' ]
-                       , actbox_name = action[ 'name' ]
-                       , actbox_url = action[ 'url' ]
-                       , actbox_category = action[ 'category' ]
-                       , props = props
-                       )
-
-        w.var_matches = PersistentMapping()
-        for k, v in w_info[ 'match' ].items():
-            w.var_matches[ str( k ) ] = tuple( [ str(x) for x in v ] )
-
-def _initDCWorkflowScripts( workflow, scripts, context ):
-
-    """ Initialize DCWorkflow scripts
-    """
-    for s_info in scripts:
-
-        id = str( s_info[ 'script_id' ] ) # no unicode!
-        meta_type = s_info[ 'meta_type' ]
-        filename = s_info[ 'filename' ]
-        file = ''
-
-        if filename:
-            file = context.readDataFile( filename )
-
-        if meta_type == PythonScript.meta_type:
-            script = PythonScript( id )
-            script.write( file )
-
-        elif meta_type == ExternalMethod.meta_type:
-            script = ExternalMethod( id
-                                   , ''
-                                   , s_info['module']
-                                   , s_info['function']
-                                   )
-
-        elif meta_type == DTMLMethod.meta_type:
-            script = DTMLMethod( file, __name__=id )
-
-        workflow.scripts._setObject( id, script )
+from Products.CMFCore.exportimport.workflow import exportWorkflowTool
+from Products.CMFCore.exportimport.workflow import importWorkflowTool

Deleted: CMF/trunk/CMFSetup/xml/wtcToolExport.xml
===================================================================
--- CMF/trunk/CMFSetup/xml/wtcToolExport.xml	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFSetup/xml/wtcToolExport.xml	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,33 +0,0 @@
-<?xml version="1.0"?>
-<workflow-tool
-        xmlns:tal="http://xml.zope.org/namespaces/tal">
- <workflow
-        workflow_id="WORKFLOW_ID"
-        meta_type="META_TYPE"
-        tal:repeat="workflow here/listWorkflowInfo"
-        tal:attributes="workflow_id workflow/id;
-                        meta_type workflow/meta_type;
-                        filename workflow/filename | default;
-                       " />
- <bindings
-        tal:define="chains here/listWorkflowChains;
-                    default_chain python: chains[ 0 ][ 1 ];
-                    overrides python: chains[ 1: ];
-                   ">
-  <default>
-   <bound-workflow
-        workflow_id="WORKFLOW_ID"
-        tal:repeat="bound default_chain"
-        tal:attributes="workflow_id bound" />
-  </default>
-  <type 
-        type_id="TYPE_ID"
-        tal:repeat="binding overrides"
-        tal:attributes="type_id python: binding[ 0 ]">
-   <bound-workflow
-        workflow_id="WORKFLOW_ID"
-        tal:repeat="bound python: binding[ 1 ]"
-        tal:attributes="workflow_id bound" />
-  </type>
- </bindings>
-</workflow-tool>

Deleted: CMF/trunk/CMFSetup/xml/wtcWorkflowExport.xml
===================================================================
--- CMF/trunk/CMFSetup/xml/wtcWorkflowExport.xml	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFSetup/xml/wtcWorkflowExport.xml	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,213 +0,0 @@
-<?xml version="1.0"?>
-<dc-workflow
-        xmlns:tal="http://xml.zope.org/namespaces/tal"
-        workflow_id="dcworkflow"
-        title="Some DCWorkflow"
-        state_variable="review_state" 
-        initial_state="visible" 
-        tal:define="info python: here.getWorkflowInfo(
-                                                options[ 'workflow_id' ] )"
-        tal:attributes="workflow_id info/id;
-                        title info/title;
-                        state_variable info/state_variable;
-                        initial_state info/initial_state">
- <permission
-        tal:repeat="permission info/permissions"
-        tal:content="permission">PERMISSION</permission>
- <state
-        state_id="pending"
-        title="Waiting for reviewer"
-        tal:repeat="state info/state_info"
-        tal:attributes="state_id state/id;
-                        title state/title;
-                       "
- ><tal:case tal:condition="state/description">
-  <description
-        tal:content="state/description">DESCRIPTION</description></tal:case>
-  <exit-transition
-        transition_id="TRANSITION_ID"
-        tal:repeat="exit state/transitions"
-        tal:attributes="transition_id exit"
-        />
-  <permission-map
-        name=""
-        acquired="True"
-        tal:repeat="perm state/permissions"
-        tal:attributes="name perm/name;
-                        acquired perm/acquired;
-                       ">
-   <permission-role
-        tal:repeat="role perm/roles"
-        tal:content="role">ROLE</permission-role>
-  </permission-map>
-  <group-map
-        name=""
-        tal:repeat="group state/groups"
-        tal:attributes="name python: group[ 0 ];
-                       ">
-   <group-role
-        tal:repeat="role python: group[ 1 ]"
-        tal:content="role">ROLE</group-role>
-  </group-map>
-  <assignment
-        name="VAR_NAME"
-        type="VAR_TYPE"
-        tal:repeat="var state/variables"
-        tal:attributes="name var/name;
-                        type var/type;
-                       "
-        tal:content="var/value">VALUE</assignment>
- </state>
- <transition
-        transition_id="Publish"
-        title="Reviewer publishes content"
-        new_state="published"
-        trigger="USER"
-        before_script=""
-        after_script=""
-        tal:repeat="transition info/transition_info"
-        tal:attributes="transition_id transition/id;
-                        title transition/title;
-                        new_state transition/new_state_id;
-                        trigger transition/trigger_type;
-                        before_script transition/script_name;
-                        after_script transition/after_script_name;
-                       "
- ><tal:case tal:condition="transition/description">
-  <description
-      tal:content="transition/description">DESCRIPTION</description></tal:case>
-  <action
-        url="URL"
-        category="CATEGORY"
-        tal:condition="transition/actbox_name"
-        tal:attributes="url transition/actbox_url;
-                        category transition/actbox_category;
-                       "
-        tal:content="transition/actbox_name">ACTION NAME</action>
-  <guard
-  ><tal:case tal:condition="transition/guard_permissions">
-   <guard-permission
-       tal:repeat="permission transition/guard_permissions"
-       tal:content="permission">PERMISSION</guard-permission></tal:case
-  ><tal:case tal:condition="transition/guard_roles">
-   <guard-role
-       tal:repeat="role transition/guard_roles"
-       tal:content="role">ROLE</guard-role></tal:case
-  ><tal:case tal:condition="transition/guard_groups">
-   <guard-group
-       tal:repeat="group transition/guard_groups"
-       tal:content="group">GROUP</guard-group></tal:case
-  ><tal:case tal:condition="transition/guard_expr">
-   <guard-expression
-       tal:content="transition/guard_expr">EXPRESSION</guard-expression
-  ></tal:case>
-  </guard>
-  <assignment
-        name="VAR_NAME"
-        tal:repeat="var transition/variables"
-        tal:attributes="name var/name"
-        tal:content="var/expr">EXPRESSION</assignment>
- </transition>
- <worklist
-        worklist_id="reviewer_queue"
-        title="For Review"
-        tal:repeat="worklist info/worklist_info"
-        tal:attributes="worklist_id worklist/id;
-                        title worklist/title;
-                       "
- ><tal:case tal:condition="worklist/description">
-  <description
-        tal:content="worklist/description">DESCRIPTION</description></tal:case>
-  <action
-        url="URL"
-        category="CATEGORY"
-        tal:condition="worklist/actbox_name"
-        tal:attributes="url worklist/actbox_url;
-                        category worklist/actbox_category;
-                       "
-        tal:content="worklist/actbox_name">ACTION NAME</action>
-  <guard
-  ><tal:case tal:condition="worklist/guard_permissions">
-   <guard-permission
-       tal:repeat="permission worklist/guard_permissions"
-       tal:content="permission">PERMISSION</guard-permission></tal:case
-  ><tal:case tal:condition="worklist/guard_roles">
-   <guard-role
-       tal:repeat="role worklist/guard_roles"
-       tal:content="role">ROLE</guard-role></tal:case
-  ><tal:case tal:condition="worklist/guard_groups">
-   <guard-group
-       tal:repeat="group worklist/guard_groups"
-       tal:content="group">GROUP</guard-group></tal:case
-  ><tal:case tal:condition="worklist/guard_expr">
-   <guard-expression
-       tal:content="worklist/guard_expr">EXPRESSION</guard-expression
-  ></tal:case>
-  </guard>
-  <match
-        name="review_state"
-        values="pending" 
-        tal:repeat="match worklist/var_match"
-        tal:attributes="name python: match[ 0 ];
-                        values python: match[ 1 ];
-                       "
-        />
- </worklist>
- <variable
-        variable_id="action"
-        for_catalog="True"
-        for_status="True"
-        update_always="True" 
-        tal:repeat="variable info/variable_info"
-        tal:attributes="variable_id variable/id;
-                        for_catalog variable/for_catalog;
-                        for_status variable/for_status;
-                        update_always variable/update_always;
-                       "
- ><tal:case tal:condition="variable/description">
-  <description
-       tal:content="variable/description">DESCRIPTION</description></tal:case>
-  <default>
-   <value
-       type="VAR_TYPE"
-       tal:attributes="type variable/default_type"
-       tal:condition="variable/default_value"
-       tal:content="variable/default_value">VALUE</value>
-   <expression
-       tal:condition="variable/default_expr"
-       tal:content="variable/default_expr">EXPRESSION</expression>
-  </default>
-  <guard
-  ><tal:case tal:condition="variable/guard_permissions">
-   <guard-permission
-       tal:repeat="permission variable/guard_permissions"
-       tal:content="permission">PERMISSION</guard-permission></tal:case
-  ><tal:case tal:condition="variable/guard_roles">
-   <guard-role
-       tal:repeat="role variable/guard_roles"
-       tal:content="role">ROLE</guard-role></tal:case
-  ><tal:case tal:condition="variable/guard_groups">
-   <guard-group
-       tal:repeat="group variable/guard_groups"
-       tal:content="group">GROUP</guard-group></tal:case
-  ><tal:case tal:condition="variable/guard_expr">
-   <guard-expression
-       tal:content="variable/guard_expr">EXPRESSION</guard-expression
-  ></tal:case>
-  </guard>
- </variable>
- <script
-        script_id="SCRIPT_ID"
-        type="Script (Python)"
-        filename="/path/to/SCRIPT_ID.py"
-        module=""
-        function=""
-        tal:repeat="script info/script_info"
-        tal:attributes="script_id script/id;
-                        type script/meta_type;
-                        filename script/filename;
-                        module script/module;
-                        function script/function
-                       "
-        />
-</dc-workflow>

Modified: CMF/trunk/CMFTopic/DEPENDENCIES.txt
===================================================================
--- CMF/trunk/CMFTopic/DEPENDENCIES.txt	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFTopic/DEPENDENCIES.txt	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,4 +1,4 @@
-Zope >= 2.8.2
+Zope >= 2.8.5
 Five >= 1.2
 CMFCore
 CMFDefault

Modified: CMF/trunk/CMFTopic/profiles/default/workflows.xml
===================================================================
--- CMF/trunk/CMFTopic/profiles/default/workflows.xml	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFTopic/profiles/default/workflows.xml	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,8 +1,6 @@
 <?xml version="1.0"?>
-<workflow-tool>
+<object name="portal_workflow" meta_type="CMF Workflow Tool">
  <bindings>
-  <type type_id="Topic">
-
-  </type>
+  <type type_id="Topic"/>
  </bindings>
-</workflow-tool>
+</object>

Modified: CMF/trunk/CMFTopic/tests/test_DateC.py
===================================================================
--- CMF/trunk/CMFTopic/tests/test_DateC.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFTopic/tests/test_DateC.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -15,17 +15,17 @@
 $Id$
 """
 
-from unittest import TestSuite, makeSuite, main
+import unittest
 import Testing
-import Zope2
-Zope2.startup()
 
 import Products
 from DateTime.DateTime import DateTime
+
 from Products.CMFCore.tests.base.testcase import PlacelessSetup
 from Products.CMFCore.tests.base.testcase import RequestTest
 from Products.CMFCore.tests.base.dummy import DummyContent
 from Products.CMFTopic.Topic import Topic
+
 from common import CriterionTestCase
 
 
@@ -165,8 +165,10 @@
         PlacelessSetup.setUp(self)
         RequestTest.setUp(self)
         zcml.load_config('meta.zcml', Products.Five)
+        zcml.load_config('permissions.zcml', Products.Five)
         zcml.load_config('configure.zcml', Products.GenericSetup)
         zcml.load_config('configure.zcml', Products.CMFCore)
+        zcml.load_config('configure.zcml', Products.DCWorkflow)
 
         factory = self.root.manage_addProduct['CMFDefault'].addConfiguredSite
         factory('site', 'CMFDefault:default', snapshot=False)
@@ -384,10 +386,10 @@
 
 
 def test_suite():
-    return TestSuite((
-        makeSuite(FriendlyDateCriterionTests),
-        makeSuite(FriendlyDateCriterionFunctionalTests),
+    return unittest.TestSuite((
+        unittest.makeSuite(FriendlyDateCriterionTests),
+        unittest.makeSuite(FriendlyDateCriterionFunctionalTests),
         ))
 
 if __name__ == '__main__':
-    main(defaultTest='test_suite')
+    unittest.main(defaultTest='test_suite')

Modified: CMF/trunk/CMFUid/DEPENDENCIES.txt
===================================================================
--- CMF/trunk/CMFUid/DEPENDENCIES.txt	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/CMFUid/DEPENDENCIES.txt	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,4 +1,4 @@
-Zope >= 2.8.2
+Zope >= 2.8.5
 Five >= 1.2
 CMFCore
 GenericSetup

Modified: CMF/trunk/DCWorkflow/DCWorkflow.py
===================================================================
--- CMF/trunk/DCWorkflow/DCWorkflow.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/DCWorkflow/DCWorkflow.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -35,9 +35,9 @@
 from Products.CMFCore.WorkflowCore import ObjectDeleted
 from Products.CMFCore.WorkflowCore import ObjectMoved
 from Products.CMFCore.WorkflowCore import WorkflowException
-from Products.CMFCore.WorkflowTool import addWorkflowFactory
 
 # DCWorkflow
+from interfaces import IDCWorkflowDefinition
 from permissions import ManagePortal
 from utils import modifyRolesForPermission
 from utils import modifyRolesForGroup
@@ -63,10 +63,9 @@
     UI methods are in WorkflowUIMixin.
     '''
 
-    implements(IWorkflowDefinition)
+    implements(IDCWorkflowDefinition, IWorkflowDefinition)
     __implements__ = z2IWorkflowDefinition
 
-    meta_type = 'Workflow'
     title = 'DC Workflow Definition'
     _isAWorkflow = 1
 
@@ -414,7 +413,7 @@
                     tdef = t
                     break
         return tdef
-        
+
     def _changeStateOf(self, ob, tdef=None, kwargs=None):
         '''
         Changes state.  Can execute multiple transitions if there are
@@ -537,7 +536,3 @@
             return new_sdef
 
 InitializeClass(DCWorkflowDefinition)
-
-
-addWorkflowFactory(DCWorkflowDefinition, id='dc_workflow',
-                   title='Web-configurable workflow')

Modified: CMF/trunk/DCWorkflow/DEPENDENCIES.txt
===================================================================
--- CMF/trunk/DCWorkflow/DEPENDENCIES.txt	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/DCWorkflow/DEPENDENCIES.txt	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,3 +1,4 @@
-Zope >= 2.8.2
+Zope >= 2.8.5
 Five >= 1.2
 CMFCore
+GenericSetup

Deleted: CMF/trunk/DCWorkflow/Default.py
===================================================================
--- CMF/trunk/DCWorkflow/Default.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/DCWorkflow/Default.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,321 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001 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.
-#
-##############################################################################
-""" Programmatically creates a workflow.
-
-$Id$
-"""
-
-from Products.CMFCore.WorkflowTool import addWorkflowFactory
-
-from DCWorkflow import DCWorkflowDefinition
-from permissions import AccessContentsInformation
-from permissions import ModifyPortalContent
-from permissions import RequestReview
-from permissions import ReviewPortalContent
-from permissions import View
-
-p_access = AccessContentsInformation
-p_modify = ModifyPortalContent
-p_request = RequestReview
-p_review = ReviewPortalContent
-p_view = View
-
-r_anon = 'Anonymous'
-r_manager = 'Manager'
-r_reviewer = 'Reviewer'
-r_owner = 'Owner'
-r_member = 'Member'
-
-
-
-def setupDefaultWorkflowRev2(wf):
-    '''
-    Sets up a DCWorkflow with the addition of a visible state,
-    the show and hide transitions, and corresponding changes.
-    wf is a DCWorkflow instance.
-    '''
-    wf.setProperties(title='CMF default workflow [Revision 2]')
-
-    for s in ('private', 'visible', 'pending', 'published'):
-        wf.states.addState(s)
-    for t in ('publish', 'reject', 'retract', 'submit', 'hide', 'show'):
-        wf.transitions.addTransition(t)
-    for v in ('action', 'actor', 'comments', 'review_history', 'time'):
-        wf.variables.addVariable(v)
-    for l in ('reviewer_queue',):
-        wf.worklists.addWorklist(l)
-    for p in (p_access, p_modify, p_view):
-        wf.addManagedPermission(p)
-
-    wf.states.setInitialState('visible')
-
-    sdef = wf.states['private']
-    sdef.setProperties(
-        title='Visible and editable only by owner',
-        transitions=('show',))
-    sdef.setPermission(p_access, 0, (r_manager, r_owner))
-    sdef.setPermission(p_view, 0, (r_manager, r_owner))
-    sdef.setPermission(p_modify, 0, (r_manager, r_owner))
-
-    sdef = wf.states['pending']
-    sdef.setProperties(
-        title='Waiting for reviewer',
-        transitions=('hide', 'publish', 'reject', 'retract',))
-    sdef.setPermission(p_access, 1, (r_manager, r_owner, r_reviewer))
-    sdef.setPermission(p_view, 1, (r_manager, r_owner, r_reviewer))
-    sdef.setPermission(p_modify, 0, (r_manager, r_reviewer))
-
-    sdef = wf.states['published']
-    sdef.setProperties(
-        title='Public',
-        transitions=('reject', 'retract',))
-    sdef.setPermission(p_access, 1, (r_anon, r_manager))
-    sdef.setPermission(p_view, 1, (r_anon, r_manager))
-    sdef.setPermission(p_modify, 0, (r_manager,))
-
-    sdef = wf.states['visible']
-    sdef.setProperties(
-        title='Visible but not published',
-        transitions=('hide', 'publish', 'submit',))
-    sdef.setPermission(p_access, 1, (r_anon, r_manager, r_reviewer))
-    sdef.setPermission(p_view, 1, (r_anon, r_manager, r_reviewer))
-    sdef.setPermission(p_modify, 0, (r_manager, r_owner))
-
-    tdef = wf.transitions['hide']
-    tdef.setProperties(
-        title='Member makes content private',
-        new_state_id='private',
-        actbox_name='Make private',
-        actbox_url='%(content_url)s/content_hide_form',
-        props={'guard_roles':r_owner})
-
-    tdef = wf.transitions['publish']
-    tdef.setProperties(
-        title='Reviewer publishes content',
-        new_state_id='published',
-        actbox_name='Publish',
-        actbox_url='%(content_url)s/content_publish_form',
-        props={'guard_permissions':p_review})
-
-    tdef = wf.transitions['reject']
-    tdef.setProperties(
-        title='Reviewer rejects submission',
-        new_state_id='visible',
-        actbox_name='Reject',
-        actbox_url='%(content_url)s/content_reject_form',
-        props={'guard_permissions':p_review})
-
-    tdef = wf.transitions['retract']
-    tdef.setProperties(
-        title='Member retracts submission',
-        new_state_id='visible',
-        actbox_name='Retract',
-        actbox_url='%(content_url)s/content_retract_form',
-        props={'guard_permissions':p_request})
-
-    tdef = wf.transitions['show']
-    tdef.setProperties(
-        title='Member makes content visible',
-        new_state_id='visible',
-        actbox_name='Make visible',
-        actbox_url='%(content_url)s/content_show_form',
-        props={'guard_roles':r_owner})
-
-    tdef = wf.transitions['submit']
-    tdef.setProperties(
-        title='Member requests publishing',
-        new_state_id='pending',
-        actbox_name='Submit',
-        actbox_url='%(content_url)s/content_submit_form',
-        props={'guard_permissions':p_request})
-
-    wf.variables.setStateVar('review_state')
-
-    vdef = wf.variables['action']
-    vdef.setProperties(description='The last transition',
-                       default_expr='transition/getId|nothing',
-                       for_status=1, update_always=1)
-
-    vdef = wf.variables['actor']
-    vdef.setProperties(description='The ID of the user who performed '
-                       'the last transition',
-                       default_expr='user/getId',
-                       for_status=1, update_always=1)
-
-    vdef = wf.variables['comments']
-    vdef.setProperties(description='Comments about the last transition',
-                       default_expr="python:state_change.kwargs.get('comment', '')",
-                       for_status=1, update_always=1)
-
-    vdef = wf.variables['review_history']
-    vdef.setProperties(description='Provides access to workflow history',
-                       default_expr="state_change/getHistory",
-                       props={'guard_permissions':
-                              p_request + ';' + p_review})
-
-    vdef = wf.variables['time']
-    vdef.setProperties(description='Time of the last transition',
-                       default_expr="state_change/getDateTime",
-                       for_status=1, update_always=1)
-
-    ldef = wf.worklists['reviewer_queue']
-    ldef.setProperties(description='Reviewer tasks',
-                       actbox_name='Pending (%(count)d)',
-                       actbox_url='%(portal_url)s/search?review_state=pending',
-                       props={'var_match_review_state':'pending',
-                              'guard_permissions':p_review})
-    
-
-def createDefaultWorkflowRev2(id):
-    '''
-    '''
-    ob = DCWorkflowDefinition(id)
-    setupDefaultWorkflowRev2(ob)
-    return ob
-
-addWorkflowFactory(createDefaultWorkflowRev2, id='default_workflow',
-                   title='Web-configurable workflow [Revision 2]')
-
-
-
-
-
-
-
-
-
-def setupDefaultWorkflowClassic(wf):
-    '''
-    Sets up a DCWorkflow as close as possible to the old DefaultWorkflow,
-    with only the private, pending, and published states.
-    wf is a DCWorkflow instance.
-    '''
-    wf.setProperties(title='CMF default workflow [Classic]')
-
-    for s in ('private', 'pending', 'published'):
-        wf.states.addState(s)
-    for t in ('publish', 'reject', 'retract', 'submit'):
-        wf.transitions.addTransition(t)
-    for v in ('action', 'actor', 'comments', 'review_history', 'time'):
-        wf.variables.addVariable(v)
-    for l in ('reviewer_queue',):
-        wf.worklists.addWorklist(l)
-    for p in (p_access, p_modify, p_view):
-        wf.addManagedPermission(p)
-
-    wf.states.setInitialState('private')
-
-    sdef = wf.states['private']
-    sdef.setProperties(
-        title='Non-visible and editable only by owner',
-        transitions=('submit', 'publish',))
-    sdef.setPermission(p_access, 0, (r_manager, r_owner))
-    sdef.setPermission(p_view, 0, (r_manager, r_owner))
-    sdef.setPermission(p_modify, 0, (r_manager, r_owner))
-
-    sdef = wf.states['pending']
-    sdef.setProperties(
-        title='Waiting for reviewer',
-        transitions=('publish', 'reject', 'retract',))
-    sdef.setPermission(p_access, 0, (r_manager, r_owner, r_reviewer))
-    sdef.setPermission(p_view, 0, (r_manager, r_owner, r_reviewer))
-    sdef.setPermission(p_modify, 0, (r_manager, r_reviewer))
-
-    sdef = wf.states['published']
-    sdef.setProperties(
-        title='Public',
-        transitions=('reject', 'retract',))
-    sdef.setPermission(p_access, 1, (r_anon, r_manager))
-    sdef.setPermission(p_view, 1, (r_anon, r_manager))
-    sdef.setPermission(p_modify, 0, (r_manager,))
-
-    tdef = wf.transitions['publish']
-    tdef.setProperties(
-        title='Reviewer publishes content',
-        new_state_id='published',
-        actbox_name='Publish',
-        actbox_url='%(content_url)s/content_publish_form',
-        props={'guard_permissions':p_review})
-
-    tdef = wf.transitions['reject']
-    tdef.setProperties(
-        title='Reviewer rejects submission',
-        new_state_id='private',
-        actbox_name='Reject',
-        actbox_url='%(content_url)s/content_reject_form',
-        props={'guard_permissions':p_review})
-
-    tdef = wf.transitions['retract']
-    tdef.setProperties(
-        title='Member retracts submission',
-        new_state_id='private',
-        actbox_name='Retract',
-        actbox_url='%(content_url)s/content_retract_form',
-        props={'guard_permissions':p_request})
-
-    tdef = wf.transitions['submit']
-    tdef.setProperties(
-        title='Member requests publishing',
-        new_state_id='pending',
-        actbox_name='Submit',
-        actbox_url='%(content_url)s/content_submit_form',
-        props={'guard_permissions':p_request})
-
-    wf.variables.setStateVar('review_state')
-
-    vdef = wf.variables['action']
-    vdef.setProperties(description='The last transition',
-                       default_expr='transition/getId|nothing',
-                       for_status=1, update_always=1)
-
-    vdef = wf.variables['actor']
-    vdef.setProperties(description='The ID of the user who performed '
-                       'the last transition',
-                       default_expr='user/getId',
-                       for_status=1, update_always=1)
-
-    vdef = wf.variables['comments']
-    vdef.setProperties(description='Comments about the last transition',
-                       default_expr="python:state_change.kwargs.get('comment', '')",
-                       for_status=1, update_always=1)
-
-    vdef = wf.variables['review_history']
-    vdef.setProperties(description='Provides access to workflow history',
-                       default_expr="state_change/getHistory",
-                       props={'guard_permissions':
-                              p_request + ';' + p_review})
-
-    vdef = wf.variables['time']
-    vdef.setProperties(description='Time of the last transition',
-                       default_expr="state_change/getDateTime",
-                       for_status=1, update_always=1)
-
-    ldef = wf.worklists['reviewer_queue']
-    ldef.setProperties(description='Reviewer tasks',
-                       actbox_name='Pending (%(count)d)',
-                       actbox_url='%(portal_url)s/search?review_state=pending',
-                       props={'var_match_review_state':'pending',
-                              'guard_permissions':p_review})
-    
-
-
-def createDefaultWorkflowClassic(id):
-    '''
-    '''
-    ob = DCWorkflowDefinition(id)
-    setupDefaultWorkflowClassic(ob)
-    return ob
-
-addWorkflowFactory(createDefaultWorkflowClassic, id='default_workflow',
-                   title='Web-configurable workflow [Classic]')
-

Copied: CMF/trunk/DCWorkflow/Extensions (from rev 40338, CMF/branches/yuppie-workflow_setup/DCWorkflow/Extensions)

Modified: CMF/trunk/DCWorkflow/__init__.py
===================================================================
--- CMF/trunk/DCWorkflow/__init__.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/DCWorkflow/__init__.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,30 +1,33 @@
 ##############################################################################
 #
 # Copyright (c) 2001 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.
-# 
+#
 ##############################################################################
 """ Web-configurable workflow.
 
 $Id$
 """
 
+from Products.CMFCore.interfaces import ISiteRoot
 from Products.CMFCore.utils import registerIcon
+from Products.GenericSetup import EXTENSION
+from Products.GenericSetup import profile_registry
+
 import DCWorkflow, States, Transitions, Variables, Worklists, Scripts
-import Default
 
 
 def initialize(context):
-    
+
     context.registerHelp(directory='help')
     context.registerHelpTitle('DCWorkflow')
-    
+
     registerIcon(DCWorkflow.DCWorkflowDefinition,
                  'images/workflow.gif', globals())
     registerIcon(States.States,
@@ -41,3 +44,11 @@
     Worklists.WorklistDefinition.icon = Worklists.Worklists.icon
     registerIcon(Scripts.Scripts,
                  'images/script.gif', globals())
+
+    profile_registry.registerProfile('revision2',
+                                     'CMF Default Workflow [Revision 2]',
+                                     'Adds revision 2 of default workflow.',
+                                     'profiles/revision2',
+                                     'DCWorkflow',
+                                     EXTENSION,
+                                     for_=ISiteRoot)

Copied: CMF/trunk/DCWorkflow/browser (from rev 40338, CMF/branches/yuppie-workflow_setup/DCWorkflow/browser)

Copied: CMF/trunk/DCWorkflow/configure.zcml (from rev 40338, CMF/branches/yuppie-workflow_setup/DCWorkflow/configure.zcml)

Copied: CMF/trunk/DCWorkflow/exportimport.py (from rev 40338, CMF/branches/yuppie-workflow_setup/DCWorkflow/exportimport.py)

Copied: CMF/trunk/DCWorkflow/interfaces.py (from rev 40338, CMF/branches/yuppie-workflow_setup/DCWorkflow/interfaces.py)

Copied: CMF/trunk/DCWorkflow/profiles (from rev 40338, CMF/branches/yuppie-workflow_setup/DCWorkflow/profiles)

Modified: CMF/trunk/DCWorkflow/tests/test_DCWorkflow.py
===================================================================
--- CMF/trunk/DCWorkflow/tests/test_DCWorkflow.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/DCWorkflow/tests/test_DCWorkflow.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -15,27 +15,21 @@
 $Id$
 """
 
-from unittest import TestCase, TestSuite, makeSuite, main
+import unittest
 import Testing
-import Zope2
-Zope2.startup()
 
 from Products.CMFCore.tests.base.dummy import DummyContent
 from Products.CMFCore.tests.base.dummy import DummySite
 from Products.CMFCore.tests.base.dummy import DummyTool
-from Products.CMFCore.WorkflowTool import addWorkflowFactory
 from Products.CMFCore.WorkflowTool import WorkflowTool
 
 
-class DCWorkflowDefinitionTests(TestCase):
+class DCWorkflowDefinitionTests(unittest.TestCase):
 
     def setUp(self):
-        from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition
-
         self.site = DummySite('site')
         self.site._setObject( 'portal_types', DummyTool() )
         self.site._setObject( 'portal_workflow', WorkflowTool() )
-        addWorkflowFactory(DCWorkflowDefinition)
         self._constructDummyWorkflow()
 
     def test_z2interfaces(self):
@@ -54,9 +48,10 @@
         verifyClass(IWorkflowDefinition, DCWorkflowDefinition)
 
     def _constructDummyWorkflow(self):
+        from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition
 
         wftool = self.site.portal_workflow
-        wftool.manage_addWorkflow('Workflow (DC Workflow Definition)', 'wf')
+        wftool._setObject('wf', DCWorkflowDefinition('wf'))
         wftool.setDefaultChain('wf')
         wf = wftool.wf
 
@@ -128,9 +123,9 @@
 
 
 def test_suite():
-    return TestSuite((
-        makeSuite(DCWorkflowDefinitionTests),
+    return unittest.TestSuite((
+        unittest.makeSuite(DCWorkflowDefinitionTests),
         ))
 
 if __name__ == '__main__':
-    main(defaultTest='test_suite')
+    unittest.main(defaultTest='test_suite')

Copied: CMF/trunk/DCWorkflow/tests/test_exportimport.py (from rev 40338, CMF/branches/yuppie-workflow_setup/DCWorkflow/tests/test_exportimport.py)

Modified: CMF/trunk/DCWorkflow/tests/test_guard.py
===================================================================
--- CMF/trunk/DCWorkflow/tests/test_guard.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/DCWorkflow/tests/test_guard.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -15,32 +15,31 @@
 $Id$
 """
 
-from unittest import TestCase, TestSuite, makeSuite, main
+import unittest
+import Testing
 
 from AccessControl import getSecurityManager
 from Products.PageTemplates.TALES import CompilerError
 
+from Products.CMFCore.tests.base.dummy import DummyContent
+from Products.CMFCore.tests.base.dummy import DummySite
+from Products.CMFCore.tests.base.dummy import DummyTool
 from Products.CMFCore.WorkflowTool import WorkflowTool
-from Products.CMFCore.WorkflowTool import addWorkflowFactory
 
 from Products.DCWorkflow.Guard import Guard
 from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition
 
-from Products.CMFCore.tests.base.dummy import DummyContent
-from Products.CMFCore.tests.base.dummy import DummySite
-from Products.CMFCore.tests.base.dummy import DummyTool
 
-class TestGuard(TestCase):
+class TestGuard(unittest.TestCase):
 
     def setUp(self):
         self.site = DummySite('site')
         self.site._setObject( 'portal_types', DummyTool() )
         self.site._setObject( 'portal_workflow', WorkflowTool() )
-        addWorkflowFactory(DCWorkflowDefinition)
 
         # Construct a workflow
         wftool = self.site.portal_workflow
-        wftool.manage_addWorkflow('Workflow (DC Workflow Definition)', 'wf')
+        wftool._setObject('wf', DCWorkflowDefinition('wf'))
         wftool.setDefaultChain('wf')
 
     def _getDummyWorkflow(self):
@@ -260,11 +259,11 @@
 
         # XXX more tests with permissions and roles
 
+
 def test_suite():
-    return TestSuite((
-        makeSuite(TestGuard),
+    return unittest.TestSuite((
+        unittest.makeSuite(TestGuard),
         ))
 
 if __name__ == '__main__':
-    main(defaultTest='test_suite')
-
+    unittest.main(defaultTest='test_suite')

Modified: CMF/trunk/DCWorkflow/utils.py
===================================================================
--- CMF/trunk/DCWorkflow/utils.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/DCWorkflow/utils.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,14 +1,14 @@
 ##############################################################################
 #
 # Copyright (c) 2001 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.
-# 
+#
 ##############################################################################
 """ Some common utilities.
 
@@ -16,15 +16,15 @@
 """
 
 import os
+
+from AccessControl.Permission import Permission
+from AccessControl.Role import gather_permissions
 from App.Common import package_home
 
 _dtmldir = os.path.join( package_home( globals() ), 'dtml' )
+_xmldir = os.path.join( package_home( globals() ), 'xml' )
 
-from AccessControl.Role import gather_permissions
-from AccessControl.Permission import Permission
-from Acquisition import aq_base
 
-
 def ac_inherited_permissions(ob, all=0):
     # Get all permissions not defined in ourself that are inherited
     # This will be a sequence of tuples with a name as the first item and

Copied: CMF/trunk/DCWorkflow/xml (from rev 40338, CMF/branches/yuppie-workflow_setup/DCWorkflow/xml)

Modified: CMF/trunk/GenericSetup/DEPENDENCIES.txt
===================================================================
--- CMF/trunk/GenericSetup/DEPENDENCIES.txt	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/GenericSetup/DEPENDENCIES.txt	2005-11-23 15:50:07 UTC (rev 40340)
@@ -1,2 +1,2 @@
-Zope >= 2.8.2
+Zope >= 2.8.5
 Five >= 1.2

Copied: CMF/trunk/GenericSetup/PythonScripts (from rev 40338, CMF/branches/yuppie-workflow_setup/GenericSetup/PythonScripts)

Modified: CMF/trunk/GenericSetup/configure.zcml
===================================================================
--- CMF/trunk/GenericSetup/configure.zcml	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/GenericSetup/configure.zcml	2005-11-23 15:50:07 UTC (rev 40340)
@@ -6,6 +6,8 @@
 
   <include package=".PluginIndexes"/>
 
+  <include package=".PythonScripts"/>
+
   <include package=".ZCatalog"/>
 
   <include package=".ZCTextIndex"/>

Modified: CMF/trunk/GenericSetup/interfaces.py
===================================================================
--- CMF/trunk/GenericSetup/interfaces.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/GenericSetup/interfaces.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -16,8 +16,9 @@
 """
 
 from zope.interface import Interface
+from zope.schema import Text
+from zope.schema import TextLine
 
-
 BASE, EXTENSION = range(1, 3)
 PURGE, UPDATE = range(1, 3)
 
@@ -587,6 +588,18 @@
         """
 
 
+class IBody(Interface):
+
+    """Body im- and exporter.
+    """
+
+    body = Text(description=u'Im- and export the object as a file body.')
+
+    mime_type = TextLine(description=u'MIME type of the file body.')
+
+    suffix = TextLine(description=u'Suffix for the file.')
+
+
 class INodeExporter(Interface):
 
     """Node exporter.
@@ -606,6 +619,7 @@
         """Import the object from the DOM node.
         """
 
+
 class IFilesystemExporter(Interface):
     """ Plugin interface for site structure export.
     """

Modified: CMF/trunk/GenericSetup/testing.py
===================================================================
--- CMF/trunk/GenericSetup/testing.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/GenericSetup/testing.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -18,10 +18,16 @@
 import unittest
 from xml.dom.minidom import parseString
 
+import Products.Five
+from Products.Five import zcml
+from zope.app import zapi
 from zope.interface.verify import verifyClass
 
+from interfaces import IBody
 from interfaces import INodeExporter
 from interfaces import INodeImporter
+from tests.common import DummyExportContext
+from tests.common import DummyImportContext
 from utils import PrettyDocument
 
 try:
@@ -30,6 +36,37 @@
     from zope.app.tests.placelesssetup import PlacelessSetup
 
 
+class BodyAdapterTestCase(PlacelessSetup, unittest.TestCase):
+
+    def _populate(self, obj):
+        pass
+
+    def _verifyImport(self, obj):
+        pass
+
+    def setUp(self):
+        PlacelessSetup.setUp(self)
+        zcml.load_config('meta.zcml', Products.Five)
+
+    def test_z3interfaces(self):
+        verifyClass(IBody, self._getTargetClass())
+
+    def test_body_get(self):
+        self._populate(self._obj)
+        context = DummyExportContext(None)
+        exporter = zapi.getMultiAdapter((self._obj, context), IBody)
+        self.assertEqual(exporter.body, self._BODY)
+
+    def test_body_set(self):
+        context = DummyImportContext(None)
+        importer = zapi.getMultiAdapter((self._obj, context), IBody)
+        importer.body = self._BODY
+        self._verifyImport(self._obj)
+        context = DummyExportContext(None)
+        exporter = zapi.getMultiAdapter((self._obj, context), IBody)
+        self.assertEqual(exporter.body, self._BODY)
+
+
 class NodeAdapterTestCase(unittest.TestCase):
 
     def _populate(self, obj):

Modified: CMF/trunk/GenericSetup/tests/common.py
===================================================================
--- CMF/trunk/GenericSetup/tests/common.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/GenericSetup/tests/common.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -21,7 +21,12 @@
 
 from Acquisition import Implicit
 from Testing.ZopeTestCase import ZopeTestCase
+from zope.interface import implements
 
+from Products.GenericSetup.interfaces import IExportContext
+from Products.GenericSetup.interfaces import IImportContext
+
+
 class OmnipotentUser(Implicit):
     """ Omnipotent User for unit testing purposes.
     """
@@ -189,6 +194,8 @@
 
 class DummyExportContext:
 
+    implements(IExportContext)
+
     def __init__( self, site, tool=None ):
         self._site = site
         self._tool = tool
@@ -212,6 +219,8 @@
 
 class DummyImportContext:
 
+    implements(IImportContext)
+
     def __init__( self, site, purge=True, encoding=None, tool=None ):
         self._site = site
         self._tool = tool

Modified: CMF/trunk/GenericSetup/utils.py
===================================================================
--- CMF/trunk/GenericSetup/utils.py	2005-11-23 11:43:31 UTC (rev 40339)
+++ CMF/trunk/GenericSetup/utils.py	2005-11-23 15:50:07 UTC (rev 40340)
@@ -21,7 +21,7 @@
 from xml.dom.minidom import Document
 from xml.dom.minidom import Element
 from xml.dom.minidom import Node
-from xml.dom.minidom import parseString as domParseString
+from xml.dom.minidom import parseString
 from xml.sax.handler import ContentHandler
 
 import Products
@@ -30,12 +30,14 @@
 from Globals import InitializeClass
 from Globals import package_home
 from TAL.TALDefs import attrEscape
+from zope.app import zapi
 from zope.interface import implements
 
 from exceptions import BadRequest
+from interfaces import IBody
 from interfaces import INodeExporter
 from interfaces import INodeImporter
-from interfaces import PURGE
+from interfaces import PURGE, UPDATE
 from permissions import ManagePortal
 
 
@@ -161,7 +163,7 @@
         if reader is not None:
             xml = reader()
 
-        dom = domParseString(xml)
+        dom = parseString(xml)
         root = dom.documentElement
 
         return self._extractNode(root)
@@ -394,6 +396,36 @@
             node.writexml(writer, indent, addindent, newl)
 
 
+class BodyAdapterBase(object):
+
+    """Body im- and exporter base.
+    """
+
+    implements(IBody)
+
+    _LOGGER_ID = ''
+
+    def __init__(self, context, environ):
+        self.context = context
+        self.environ = environ
+        self._logger = environ.getLogger(self._LOGGER_ID)
+
+    def _exportBody(self):
+        """Export the object as a file body.
+        """
+        return ''
+
+    def _importBody(self, body):
+        """Import the object from the file body.
+        """
+
+    body = property(_exportBody, _importBody)
+
+    mime_type = 'text/plain'
+
+    suffix = ''
+
+
 class NodeAdapterBase(object):
 
     """Node im- and exporter base.
@@ -436,6 +468,32 @@
     def _convertToBoolean(self, val):
         return val.lower() in ('true', 'yes', '1')
 
+
+class XMLAdapterBase(BodyAdapterBase, NodeAdapterBase):
+
+    """XML im- and exporter base.
+    """
+
+    def _exportBody(self):
+        """Export the object as a file body.
+        """
+        doc = PrettyDocument()
+        doc.appendChild(self.exportNode(doc))
+        return doc.toprettyxml(' ')
+
+    def _importBody(self, body):
+        """Import the object from the file body.
+        """
+        mode = self.environ.shouldPurge() and PURGE or UPDATE
+        self.importNode(parseString(body).documentElement, mode=mode)
+
+    body = property(_exportBody, _importBody)
+
+    mime_type = 'text/xml'
+
+    suffix = '.xml'
+
+
 class ObjectManagerHelpers(object):
 
     """ObjectManager im- and export helpers.
@@ -494,7 +552,9 @@
                         pass
 
             obj = getattr(self.context, obj_id)
-            INodeImporter(obj).importNode(child, mode)
+            importer = INodeImporter(obj, None)
+            if importer:
+                importer.importNode(child, mode)
 
 
 class PropertyManagerHelpers(object):
@@ -588,3 +648,34 @@
                 prop_value = self._getNodeText(child).encode('utf-8')
 
             obj._updateProperty(prop_id, prop_value)
+
+
+def exportObjects(parent, parent_path, context):
+    """ Export subobjects recursively.
+    """
+    for obj in parent.objectValues():
+        path = '%s/%s' % (parent_path, obj.getId().replace(' ', '_'))
+
+        exporter = zapi.queryMultiAdapter((obj, context), IBody)
+        if exporter:
+            filename = '%s%s' % (path, exporter.suffix)
+            context.writeDataFile(filename, exporter.body, exporter.mime_type)
+
+        if getattr(obj, 'objectValues', False):
+            exportObjects(obj, path, context)
+
+def importObjects(parent, parent_path, context):
+    """ Import subobjects recursively.
+    """
+    for obj in parent.objectValues():
+        path = '%s/%s' % (parent_path, obj.getId().replace(' ', '_'))
+
+        importer = zapi.queryMultiAdapter((obj, context), IBody)
+        if importer:
+            filename = '%s%s' % (path, importer.suffix)
+            body = context.readDataFile(filename)
+            if body:
+                importer.body = body
+
+        if getattr(obj, 'objectValues', False):
+            importObjects(obj, path, context)



More information about the CMF-checkins mailing list