[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() <= 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() <= 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