[Checkins] SVN: Products.CMFCore/trunk/Products/CMFCore/ - actions tool export/import: The actions tool export/import mechanism

Jens Vagelpohl jens at dataflake.org
Sat Oct 4 09:12:40 EDT 2008


Log message for revision 91742:
  - actions tool export/import: The actions tool export/import mechanism 
    is no longer attempting to handle actions stored on tools other than
    itself. Other tools are themselves responsible for their actions.
    The importer has been fixed to add all action providers to the actions   
    tool, not just a select list of providers we know about.
    (https://bugs.launchpad.net/zope-cmf/+bug/177675)
  

Changed:
  U   Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt
  U   Products.CMFCore/trunk/Products/CMFCore/exportimport/actions.py
  U   Products.CMFCore/trunk/Products/CMFCore/exportimport/tests/test_actions.py

-=-
Modified: Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt	2008-10-04 11:00:03 UTC (rev 91741)
+++ Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt	2008-10-04 13:12:38 UTC (rev 91742)
@@ -4,6 +4,13 @@
 2.2.0 (unreleased)
 ------------------
 
+- actions tool export/import: The actions tool export/import mechanism 
+  is no longer attempting to handle actions stored on tools other than
+  itself. Other tools are themselves responsible for their actions.
+  The importer has been fixed to add all action providers to the actions 
+  tool, not just a select list of providers we know about.
+  (https://bugs.launchpad.net/zope-cmf/+bug/177675)
+
 - tool interfaces: Replace non-existing IMember interface with the
   correct IMemberData.
 

Modified: Products.CMFCore/trunk/Products/CMFCore/exportimport/actions.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/exportimport/actions.py	2008-10-04 11:00:03 UTC (rev 91741)
+++ Products.CMFCore/trunk/Products/CMFCore/exportimport/actions.py	2008-10-04 13:12:38 UTC (rev 91742)
@@ -32,9 +32,7 @@
 from Products.CMFCore.interfaces import IActionsTool
 from Products.CMFCore.utils import getToolByName
 
-_SPECIAL_PROVIDERS = ('portal_actions', 'portal_types', 'portal_workflow')
 
-
 class ActionCategoryNodeAdapter(NodeAdapterBase, ObjectManagerHelpers,
                                 PropertyManagerHelpers):
 
@@ -134,14 +132,22 @@
         for provider_id in self.context.listActionProviders():
             child = self._doc.createElement('action-provider')
             child.setAttribute('name', provider_id)
-            # BBB: for CMF 1.6 profiles
-            sub = self._extractOldstyleActions(provider_id)
-            child.appendChild(sub)
+            # BBB: for CMF 1.6 action settings
+            # We only do this for the portal_actions tool itself. Other 
+            # providers are responsible for their own action import/export.
+            if provider_id == 'portal_actions':
+                sub = self._extractOldstyleActions(provider_id)
+                child.appendChild(sub)
+
             fragment.appendChild(child)
+
         return fragment
 
     def _extractOldstyleActions(self, provider_id):
-        # BBB: for CMF 1.6 profiles
+        # BBB: for CMF 1.6 action settings
+        # This method collects "old-style" action information and
+        # formats it for import as "new-style" actions
+
         fragment = self._doc.createDocumentFragment()
 
         provider = getToolByName(self.context, provider_id)
@@ -189,15 +195,23 @@
                     self.context.deleteActionProvider(provider_id)
                 continue
 
-            if provider_id in _SPECIAL_PROVIDERS and \
-                    provider_id not in self.context.listActionProviders():
+            if provider_id not in self.context.listActionProviders():
                 self.context.addActionProvider(provider_id)
 
-            # BBB: for CMF 1.6 profiles
-            self._initOldstyleActions(child)
+            # BBB: for CMF 1.6 action setting exports
+            # We only do this for the portal_actions tool itself. Other 
+            # providers are responsible for their own action import/export.
+            if provider_id == 'portal_actions':
+                self._initOldstyleActions(child)
 
     def _initOldstyleActions(self, node):
-        # BBB: for CMF 1.6 profiles
+        # BBB: for CMF 1.6 action setting exports
+        # This code transparently migrates old export data containing
+        # "old-style" action information to "new-style" actions.
+        # It does this by synthesizing "new-style" export data from the
+        # existing export and then importing that instead of the 
+        # "real" export data, which also moves these actions into the
+        # actions tool.
         doc = node.ownerDocument
         fragment = doc.createDocumentFragment()
         for child in node.childNodes:

Modified: Products.CMFCore/trunk/Products/CMFCore/exportimport/tests/test_actions.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/exportimport/tests/test_actions.py	2008-10-04 11:00:03 UTC (rev 91741)
+++ Products.CMFCore/trunk/Products/CMFCore/exportimport/tests/test_actions.py	2008-10-04 13:12:38 UTC (rev 91742)
@@ -90,11 +90,18 @@
 </object>
 """
 
-_NORMAL_EXPORT = """\
+_OLD_EXPORT = """\
 <?xml version="1.0"?>
 <object name="portal_actions" meta_type="CMF Actions Tool"
    xmlns:i18n="http://xml.zope.org/namespaces/i18n">
- <action-provider name="portal_actions"/>
+ <action-provider name="portal_actions">
+  <action action_id="baz"
+          title="Baz"
+          url_expr="string:${object_url}/baz"
+          condition_expr="python:1"
+          category="dummy"
+          visible="True"/>
+ </action-provider>
  <action-provider name="portal_foo">
   <action action_id="foo"
           title="Foo"
@@ -116,33 +123,41 @@
 </object>
 """
 
+_NORMAL_EXPORT = """\
+<?xml version="1.0"?>
+<object name="portal_actions" meta_type="CMF Actions Tool"
+   xmlns:i18n="http://xml.zope.org/namespaces/i18n">
+ <action-provider name="portal_actions">
+  <action action_id="baz"
+          title="Baz"
+          url_expr="string:${object_url}/baz"
+          condition_expr="python:1"
+          category="dummy"
+          visible="True"/>
+ </action-provider>
+ <action-provider name="portal_foo"/>
+ <action-provider name="portal_bar"/>
+</object>
+"""
+
 _NEWSYTLE_EXPORT = """\
 <?xml version="1.0"?>
 <object name="portal_actions" meta_type="CMF Actions Tool"
    xmlns:i18n="http://xml.zope.org/namespaces/i18n">
  <action-provider name="portal_actions"/>
+ <action-provider name="portal_foo"/>
+ <action-provider name="portal_bar"/>
  <object name="dummy" meta_type="CMF Action Category">
   <property name="title"></property>
-  <object name="foo" meta_type="CMF Action">
-   <property name="title">Foo</property>
+  <object name="baz" meta_type="CMF Action">
+   <property name="title">Baz</property>
    <property name="description"></property>
-   <property name="url_expr">string:${object_url}/foo</property>
+   <property name="url_expr">string:${object_url}/baz</property>
    <property name="icon_expr"></property>
    <property name="available_expr">python:1</property>
    <property name="permissions"></property>
    <property name="visible">True</property>
   </object>
-  <object name="bar" meta_type="CMF Action">
-   <property name="title">Bar</property>
-   <property name="description"></property>
-   <property name="url_expr">string:${object_url}/bar</property>
-   <property name="icon_expr"></property>
-   <property name="available_expr">python:0</property>
-   <property name="permissions">
-    <element value="Manage portal"/>
-   </property>
-   <property name="visible">False</property>
-  </object>
  </object>
 </object>
 """
@@ -181,8 +196,8 @@
    <element value="View" /></property>
   <property name="visible">True</property>
  </object>
- <object name="foo" insert-after="*">
-  <property name="icon_expr">string:foo_icon.png</property>
+ <object name="baz" insert-after="*">
+  <property name="icon_expr">string:baz_icon.png</property>
  </object>
  </object>
 </object>
@@ -396,6 +411,15 @@
                 import exportActionProviders
 
         site = self._initSite()
+        # Set up an old action for added difficulty
+        site.portal_actions.addAction(id='baz',
+                                      name='Baz',
+                                      action='baz',
+                                      condition='python:1',
+                                      permission=(),
+                                      category='dummy',
+                                      visible=1)
+
         context = DummyExportContext(site)
         exportActionProviders(context)
 
@@ -488,18 +512,21 @@
         self.failUnless('portal_actions' in atool.listActionProviders())
 
         context = DummyImportContext(site)
-        context._files['actions.xml'] = _NORMAL_EXPORT
+        context._files['actions.xml'] = _OLD_EXPORT
         importActionProviders(context)
 
-        self.assertEqual(len(atool.listActionProviders()), 1)
-        self.failIf('portal_foo' in atool.listActionProviders())
+        self.assertEqual(len(atool.listActionProviders()), 3)
+        self.failUnless('portal_bar' in atool.listActionProviders())
+        self.failUnless('portal_foo' in atool.listActionProviders())
         self.failUnless('portal_actions' in atool.listActionProviders())
 
         self.assertEqual(len(atool.objectIds()), 1)
         self.failUnless('dummy' in atool.objectIds())
-        self.assertEqual(len(atool.dummy.objectIds()) , 2)
-        self.failUnless('foo' in atool.dummy.objectIds())
-        self.failUnless('bar' in atool.dummy.objectIds())
+        # Only one action appears. The importer only deals with actions
+        # defined by the actions tool. Other tools are responsible for
+        # exporting/importing actions themselves.
+        self.assertEqual(len(atool.dummy.objectIds()) , 1)
+        self.failUnless('baz' in atool.dummy.objectIds())
         self.failIf(foo.listActions())
         self.failIf(bar.listActions())
 
@@ -552,19 +579,19 @@
         context._files['actions.xml'] = _NEWSYTLE_EXPORT
         importActionProviders(context)
 
-        self.assertEqual(len(atool.listActionProviders()), 1)
+        self.assertEqual(len(atool.listActionProviders()), 3)
         self.assertEqual(atool.objectIds(), ['dummy'])
-        self.assertEqual(atool.dummy.objectIds(), ['foo', 'bar'])
-        self.assertEqual(atool.dummy.foo.icon_expr, '')
+        self.assertEqual(atool.dummy.objectIds(), ['baz'])
+        self.assertEqual(atool.dummy.baz.icon_expr, '')
 
         context = DummyImportContext(site, False)
         context._files['actions.xml'] = _INSERT_IMPORT
         importActionProviders(context)
 
-        self.assertEqual(len(atool.listActionProviders()), 1)
+        self.assertEqual(len(atool.listActionProviders()), 3)
         self.assertEqual(atool.objectIds(), ['dummy'])
-        self.assertEqual(atool.dummy.objectIds(), ['spam', 'bar', 'foo'])
-        self.assertEqual(atool.dummy.foo.icon_expr, 'string:foo_icon.png')
+        self.assertEqual(atool.dummy.objectIds(), ['spam', 'baz'])
+        self.assertEqual(atool.dummy.baz.icon_expr, 'string:baz_icon.png')
 
     def test_remove_skip_purge(self):
         from Products.CMFCore.exportimport.actions \



More information about the Checkins mailing list