From 76207531557d62074afd13e7ac4d92b9ee1d8a85 Mon Sep 17 00:00:00 2001
From: Rafael Monnerat <rafael@nexedi.com>
Date: Fri, 11 Jun 2010 14:49:22 +0000
Subject: [PATCH] Added support to use strings to upgradeObjectClass.

This change allows use python scripts to upgrade Object Class without write external methods for it. The from_class and to_class arguments can be used like followed:

 from_class="Products.ERP5Type.Document.Folder.Folder"
 to_class="Products.ERP5Type.Document.Category.Category"

or use previous behaviour:

 from_class = folder.__class__
 to_class = category.__class__




git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@36278 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5Type/Core/Folder.py      | 25 ++++++++++++++++++++-----
 product/ERP5Type/tests/testFolder.py | 20 +++++++++++++++++++-
 2 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/product/ERP5Type/Core/Folder.py b/product/ERP5Type/Core/Folder.py
index 560f49d532..e6f2abfcb1 100644
--- a/product/ERP5Type/Core/Folder.py
+++ b/product/ERP5Type/Core/Folder.py
@@ -1084,13 +1084,28 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn,
   security.declareProtected( Permissions.ModifyPortalContent, 'upgradeObjectClass' )
   def upgradeObjectClass(self, test_before, from_class, to_class, test_after):
     """
-    upgrade the class of all objects inside this
-    particular folder
-     test_before and test_after have to be a method with one parameter.
-     migrations is a dictionnary of class, { from_class : to_class }
+    Upgrade the class of all objects inside this particular folder:
+      test_before and test_after have to be a method with one parameter.
+
+      from_class and to_class can be classes (o.__class___) or strings like:
+        'Products.ERP5Type.Document.Folder.Folder'
+     
     """
-    #LOG("upradeObjectClass: folder ",0,self.id)
+    #LOG("upgradeObjectClass: folder ", 0, self.id)
     test_list = []
+    def getClassFromString(a_klass):
+      from_module = '.'.join(a_klass.split('.')[:-1])
+      real_klass = a_klass.split('.')[-1]
+      # XXX It is possible that API Change for Python 2.6.
+      mod = __import__(from_module, globals(), locals(),  [real_klass])
+      return getattr(mod, real_klass)
+
+    if isinstance(from_class, type('')):
+      from_class = getClassFromString(from_class)
+
+    if isinstance(to_class, type('')):
+      to_class = getClassFromString(to_class)
+
     folder = self.getObject()
     for o in self.listFolderContents():
       # Make sure this sub object is not the same as object
diff --git a/product/ERP5Type/tests/testFolder.py b/product/ERP5Type/tests/testFolder.py
index e6b4102a2f..ea2ff1be87 100644
--- a/product/ERP5Type/tests/testFolder.py
+++ b/product/ERP5Type/tests/testFolder.py
@@ -221,7 +221,25 @@ class TestFolder(ERP5TypeTestCase, LogInterceptor):
       self.assertNotEquals(self.folder[subobject.getId()][obj.getId()].__class__, from_class)
       self.assertEquals([1, 1], result)
 
-
+    def test_upgradeObjectClassWithStrings(self):
+      """ Test if it changes Object Class """
+      type_list = ['Folder', 'Category' ]
+      self._setAllowedContentTypesForFolderType(type_list)
+      obj = self.folder.newContent(portal_type="Category")
+      from_class_as_string = 'Products.ERP5Type.Document.Category.Category'
+      to_class_as_string = 'Products.ERP5Type.Document.Folder.Folder'
+      from_class = obj.__class__
+      to_class = self.folder.__class__
+      createZODBPythonScript(self.getPortal().portal_skins.custom,
+                     "test_upgradeObject", 'x',
+                     'return [1]')
+      test_script = self.getPortal().portal_skins.custom.test_upgradeObject
+      result = self.folder.upgradeObjectClass(test_script, from_class_as_string,
+                                              to_class_as_string, test_script)
+      transaction.commit()
+      self.assertEquals(self.folder[obj.getId()].__class__, to_class)
+      self.assertNotEquals(self.folder[obj.getId()].__class__, from_class)
+      self.assertEquals([1], result)
 
 def test_suite():
   suite = unittest.TestSuite()
-- 
2.30.9