Commit 8a3acd8e authored by Arnaud Fontaine's avatar Arnaud Fontaine

Implement migration of bt5 Document from filesystem to ZODB.

DocumentTemplateItem was renamed to FilesystemDocumentTemplateItem which will
be kept until the migration to Components is over. Also, move Extension
Component tests to its parent class (TestDocumentTemplateItem) to add tests
for bt5 Document.
parent 2f6e5176
...@@ -3327,7 +3327,9 @@ class ModuleTemplateItem(BaseTemplateItem): ...@@ -3327,7 +3327,9 @@ class ModuleTemplateItem(BaseTemplateItem):
# Do not remove any module for safety. # Do not remove any module for safety.
pass pass
class DocumentTemplateItem(BaseTemplateItem): # XXX-arnau: when everything has been migrated to Components, everything in
# this class should be moved to DocumentTemplateItem
class FilesystemDocumentTemplateItem(BaseTemplateItem):
local_file_reader_name = staticmethod(readLocalDocument) local_file_reader_name = staticmethod(readLocalDocument)
local_file_writer_name = staticmethod(writeLocalDocument) local_file_writer_name = staticmethod(writeLocalDocument)
local_file_importer_name = staticmethod(importLocalDocument) local_file_importer_name = staticmethod(importLocalDocument)
...@@ -3400,7 +3402,7 @@ class DocumentTemplateItem(BaseTemplateItem): ...@@ -3400,7 +3402,7 @@ class DocumentTemplateItem(BaseTemplateItem):
update_dict = kw.get('object_to_update') update_dict = kw.get('object_to_update')
force = kw.get('force') force = kw.get('force')
if context.getTemplateFormatVersion() == 1: if context.getTemplateFormatVersion() == 1:
need_reset = isinstance(self, DocumentTemplateItem) need_reset = isinstance(self, FilesystemDocumentTemplateItem)
for key in self._objects.keys(): for key in self._objects.keys():
# to achieve non data migration fresh installation parameters # to achieve non data migration fresh installation parameters
# differ from upgrade parameteres, so here the check have to be # differ from upgrade parameteres, so here the check have to be
...@@ -3454,7 +3456,7 @@ class DocumentTemplateItem(BaseTemplateItem): ...@@ -3454,7 +3456,7 @@ class DocumentTemplateItem(BaseTemplateItem):
else: else:
object_keys = self._archive.keys() object_keys = self._archive.keys()
if object_keys: if object_keys:
if isinstance(self, DocumentTemplateItem): if isinstance(self, FilesystemDocumentTemplateItem):
self._resetDynamicModules() self._resetDynamicModules()
for key in object_keys: for key in object_keys:
self.local_file_remover_name(key) self.local_file_remover_name(key)
...@@ -3478,10 +3480,10 @@ class DocumentTemplateItem(BaseTemplateItem): ...@@ -3478,10 +3480,10 @@ class DocumentTemplateItem(BaseTemplateItem):
text = file.read() text = file.read()
self._objects[file_name[:-3]] = text self._objects[file_name[:-3]] = text
class FilesystemToZodbTemplateItem(DocumentTemplateItem, class FilesystemToZodbTemplateItem(FilesystemDocumentTemplateItem,
ObjectTemplateItem): ObjectTemplateItem):
""" """
Abstract class to allow migration from DocumentTemplateItem to Abstract class to allow migration from FilesystemDocumentTemplateItem to
ObjectTemplateItem, this is useful for migration from filesystem to ZODB for ObjectTemplateItem, this is useful for migration from filesystem to ZODB for
PropertySheets and Components PropertySheets and Components
""" """
...@@ -3526,14 +3528,15 @@ class FilesystemToZodbTemplateItem(DocumentTemplateItem, ...@@ -3526,14 +3528,15 @@ class FilesystemToZodbTemplateItem(DocumentTemplateItem,
def _filesystemCompatibilityWrapper(method_name, object_dict_name): def _filesystemCompatibilityWrapper(method_name, object_dict_name):
""" """
Call ObjectTemplateItem method when the objects have already been Call ObjectTemplateItem method when the objects have already been
migrated, otherwise fallback on DocumentTemplateItem method for migrated, otherwise fallback on FilesystemDocumentTemplateItem method for
backward-compatibility backward-compatibility
""" """
def inner(self, *args, **kw): def inner(self, *args, **kw):
if self._is_already_migrated(getattr(self, object_dict_name).keys()): if self._is_already_migrated(getattr(self, object_dict_name).keys()):
result = getattr(ObjectTemplateItem, method_name)(self, *args, **kw) result = getattr(ObjectTemplateItem, method_name)(self, *args, **kw)
else: else:
result = getattr(DocumentTemplateItem, method_name)(self, *args, **kw) result = getattr(FilesystemDocumentTemplateItem,
method_name)(self, *args, **kw)
return result return result
return inner return inner
...@@ -3546,7 +3549,8 @@ class FilesystemToZodbTemplateItem(DocumentTemplateItem, ...@@ -3546,7 +3549,8 @@ class FilesystemToZodbTemplateItem(DocumentTemplateItem,
if file_name.endswith('.xml'): if file_name.endswith('.xml'):
return ObjectTemplateItem._importFile(self, file_name, *args, **kw) return ObjectTemplateItem._importFile(self, file_name, *args, **kw)
else: else:
return DocumentTemplateItem._importFile(self, file_name, *args, **kw) return FilesystemDocumentTemplateItem._importFile(self, file_name,
*args, **kw)
def uninstall(self, *args, **kw): def uninstall(self, *args, **kw):
# Only for uninstall, the path of objects can be given as a # Only for uninstall, the path of objects can be given as a
...@@ -3560,7 +3564,7 @@ class FilesystemToZodbTemplateItem(DocumentTemplateItem, ...@@ -3560,7 +3564,7 @@ class FilesystemToZodbTemplateItem(DocumentTemplateItem,
if self._is_already_migrated(object_keys): if self._is_already_migrated(object_keys):
return ObjectTemplateItem.uninstall(self, *args, **kw) return ObjectTemplateItem.uninstall(self, *args, **kw)
else: else:
return DocumentTemplateItem.uninstall(self, *args, **kw) return FilesystemDocumentTemplateItem.uninstall(self, *args, **kw)
def remove(self, context, **kw): def remove(self, context, **kw):
""" """
...@@ -3656,7 +3660,7 @@ class FilesystemToZodbTemplateItem(DocumentTemplateItem, ...@@ -3656,7 +3660,7 @@ class FilesystemToZodbTemplateItem(DocumentTemplateItem,
def install(self, context, **kw): def install(self, context, **kw):
if not self._perform_migration: if not self._perform_migration:
return DocumentTemplateItem.install(self, context, **kw) return FilesystemDocumentTemplateItem.install(self, context, **kw)
# With format 0 of Business Template, the objects are stored in # With format 0 of Business Template, the objects are stored in
# '_archive' whereas they are stored in '_objects' with format # '_archive' whereas they are stored in '_objects' with format
...@@ -3692,9 +3696,9 @@ class PropertySheetTemplateItem(FilesystemToZodbTemplateItem): ...@@ -3692,9 +3696,9 @@ class PropertySheetTemplateItem(FilesystemToZodbTemplateItem):
2/ The Property Sheets will all be migrated when installing the 2/ The Property Sheets will all be migrated when installing the
Business Template. Business Template.
Therefore, this is an all or nothing migration, meaning that only Therefore, this is an all or nothing migration, meaning that only methods of
methods of DocumentTemplateItem will be called before the migration FilesystemDocumentTemplateItem will be called before the migration has been
has been performed, then ObjectTemplateItem methods afterwards. performed, then ObjectTemplateItem methods afterwards.
""" """
# Only meaningful for filesystem Property Sheets # Only meaningful for filesystem Property Sheets
local_file_reader_name = staticmethod(readLocalPropertySheet) local_file_reader_name = staticmethod(readLocalPropertySheet)
...@@ -3744,16 +3748,16 @@ class PropertySheetTemplateItem(FilesystemToZodbTemplateItem): ...@@ -3744,16 +3748,16 @@ class PropertySheetTemplateItem(FilesystemToZodbTemplateItem):
return PropertySheetDocument.importFromFilesystemDefinition(tool, klass) return PropertySheetDocument.importFromFilesystemDefinition(tool, klass)
class ConstraintTemplateItem(DocumentTemplateItem): class ConstraintTemplateItem(FilesystemDocumentTemplateItem):
local_file_reader_name = staticmethod(readLocalConstraint) local_file_reader_name = staticmethod(readLocalConstraint)
local_file_writer_name = staticmethod(writeLocalConstraint) local_file_writer_name = staticmethod(writeLocalConstraint)
local_file_importer_name = staticmethod(importLocalConstraint) local_file_importer_name = staticmethod(importLocalConstraint)
local_file_remover_name = staticmethod(removeLocalConstraint) local_file_remover_name = staticmethod(removeLocalConstraint)
from Products.ERP5Type.Core.ExtensionComponent import ExtensionComponent as \ from Products.ERP5Type.Core.DocumentComponent import DocumentComponent as \
ExtensionComponentDocument DocumentComponentDocument
class ExtensionTemplateItem(FilesystemToZodbTemplateItem): class DocumentTemplateItem(FilesystemToZodbTemplateItem):
""" """
Extensions are now stored in ZODB rather than on the filesystem. However, Extensions are now stored in ZODB rather than on the filesystem. However,
some Business Templates may still have filesystem Extensions which need to some Business Templates may still have filesystem Extensions which need to
...@@ -3764,12 +3768,16 @@ class ExtensionTemplateItem(FilesystemToZodbTemplateItem): ...@@ -3764,12 +3768,16 @@ class ExtensionTemplateItem(FilesystemToZodbTemplateItem):
_tool_id = 'portal_components' _tool_id = 'portal_components'
# Only meaningful for filesystem Extensions @staticmethod
local_file_reader_name = staticmethod(readLocalExtension) def _getZodbObjectId(id):
local_file_writer_name = staticmethod(writeLocalExtension) return 'erp5.component.document.%s' % id
# Extension needs no import
local_file_importer_name = None @staticmethod
local_file_remover_name = staticmethod(removeLocalExtension) def _getFilesystemPath(class_id):
from App.config import getConfiguration
return os.path.join(getConfiguration().instancehome,
"Document",
"%s.py" % class_id)
def _importFile(self, file_name, file_obj): def _importFile(self, file_name, file_obj):
if (file_name.endswith('.py') and if (file_name.endswith('.py') and
...@@ -3805,6 +3813,30 @@ class ExtensionTemplateItem(FilesystemToZodbTemplateItem): ...@@ -3805,6 +3813,30 @@ class ExtensionTemplateItem(FilesystemToZodbTemplateItem):
XMLExportImport.exportXML(obj._p_jar, obj._p_oid, f) XMLExportImport.exportXML(obj._p_jar, obj._p_oid, f)
bta.addObject(f, key, path=path) bta.addObject(f, key, path=path)
@staticmethod
def _migrateFromFilesystem(tool,
filesystem_path,
filesystem_file,
class_id):
return DocumentComponentDocument.importFromFilesystem(tool,
filesystem_path)
from Products.ERP5Type.Core.ExtensionComponent import ExtensionComponent as \
ExtensionComponentDocument
class ExtensionTemplateItem(DocumentTemplateItem):
"""
Extensions are now stored in ZODB rather than on the filesystem. However,
some Business Templates may still have filesystem Extensions which need to
be migrated to the ZODB.
"""
# Only meaningful for filesystem Extensions
local_file_reader_name = staticmethod(readLocalExtension)
local_file_writer_name = staticmethod(writeLocalExtension)
# Extension needs no import
local_file_importer_name = None
local_file_remover_name = staticmethod(removeLocalExtension)
@staticmethod @staticmethod
def _getZodbObjectId(id): def _getZodbObjectId(id):
return 'erp5.component.extension.%s' % id return 'erp5.component.extension.%s' % id
...@@ -3824,7 +3856,7 @@ class ExtensionTemplateItem(FilesystemToZodbTemplateItem): ...@@ -3824,7 +3856,7 @@ class ExtensionTemplateItem(FilesystemToZodbTemplateItem):
return ExtensionComponentDocument.importFromFilesystem(tool, return ExtensionComponentDocument.importFromFilesystem(tool,
filesystem_path) filesystem_path)
class TestTemplateItem(DocumentTemplateItem): class TestTemplateItem(FilesystemDocumentTemplateItem):
local_file_reader_name = staticmethod(readLocalTest) local_file_reader_name = staticmethod(readLocalTest)
local_file_writer_name = staticmethod(writeLocalTest) local_file_writer_name = staticmethod(writeLocalTest)
# Test needs no import # Test needs no import
......
...@@ -6565,6 +6565,8 @@ class TestBusinessTemplate(BusinessTemplateMixin): ...@@ -6565,6 +6565,8 @@ class TestBusinessTemplate(BusinessTemplateMixin):
sequence_list.addSequenceString(sequence_string) sequence_list.addSequenceString(sequence_string)
sequence_list.play(self) sequence_list.play(self)
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
class TestDocumentTemplateItem(BusinessTemplateMixin): class TestDocumentTemplateItem(BusinessTemplateMixin):
document_title = 'UnitTest' document_title = 'UnitTest'
document_data = """class UnitTest: document_data = """class UnitTest:
...@@ -6660,6 +6662,112 @@ class TestDocumentTemplateItem(BusinessTemplateMixin): ...@@ -6660,6 +6662,112 @@ class TestDocumentTemplateItem(BusinessTemplateMixin):
sequence_list.addSequenceString(sequence_string) sequence_list.addSequenceString(sequence_string)
sequence_list.play(self) sequence_list.play(self)
component_module = DocumentComponent._getDynamicModuleNamespace()
component_portal_type = DocumentComponent.portal_type
def getBusinessTemplateList(self):
return (super(TestDocumentTemplateItem, self).getBusinessTemplateList() +
('erp5_core_component',))
def stepCheckZodbDocumentRemoved(self, sequence=None, **kw):
component_tool = self.getPortalObject().portal_components
component_id = '%s.%s' % (self.component_module, sequence['document_title'])
self.failIf(component_id in component_tool.objectIds())
def stepRemoveZodbDocument(self, sequence=None, **kw):
"""
Remove Property Sheet, but only from ZODB
"""
component_id = '%s.%s' % (self.component_module, sequence['document_title'])
self.portal.portal_components.manage_delObjects([component_id])
def stepCheckDocumentMigration(self, sequence=None, **kw):
"""
Check migration of Document from the Filesystem to ZODB
"""
component_id = '%s.%s' % (self.component_module, sequence['document_title'])
component_tool = self.getPortalObject().portal_components
self.failUnless(component_id in component_tool.objectIds())
component = getattr(component_tool, component_id)
self.assertEquals(component.getReference(), self.document_title)
self.assertEquals(component.getTextContent(), self.document_data)
self.assertEquals(component.getPortalType(), self.component_portal_type)
def stepCheckForkedMigrationExport(self, sequence=None, **kw):
component_bt_tool_path = os.path.join(sequence['template_path'],
self.__class__.__name__.replace('Test', ''),
'portal_components')
self.assertTrue(os.path.exists(component_bt_tool_path))
component_id = '%s.%s' % (self.component_module, sequence['document_title'])
base_path = os.path.join(component_bt_tool_path, component_id)
python_source_code_path = base_path + '.py'
self.assertTrue(os.path.exists(python_source_code_path))
source_code = sequence['document_data']
with open(python_source_code_path) as f:
self.assertEquals(f.read(), source_code)
xml_path = base_path + '.xml'
self.assertTrue(os.path.exists(xml_path))
first_line = source_code.split('\n', 1)[0]
with open(xml_path) as f:
for line in f:
self.failIf(first_line in line)
def test_BusinessTemplateWithDocumentMigration(self):
sequence_list = SequenceList()
sequence_string = '\
CreateDocument \
CreateNewBusinessTemplate \
UseExportBusinessTemplate \
AddDocumentToBusinessTemplate \
CheckModifiedBuildingState \
CheckNotInstalledInstallationState \
BuildBusinessTemplate \
CheckBuiltBuildingState \
CheckNotInstalledInstallationState \
CheckObjectPropertiesInBusinessTemplate \
SaveBusinessTemplate \
CheckBuiltBuildingState \
CheckNotInstalledInstallationState \
RemoveDocument \
RemoveBusinessTemplate \
RemoveAllTrashBins \
ImportBusinessTemplate \
UseImportBusinessTemplate \
CheckBuiltBuildingState \
CheckNotInstalledInstallationState \
InstallWithoutForceBusinessTemplate \
Tic \
CheckInstalledInstallationState \
CheckBuiltBuildingState \
CheckNoTrashBin \
CheckSkinsLayers \
CheckDocumentMigration \
CheckDocumentRemoved \
UninstallBusinessTemplate \
CheckBuiltBuildingState \
CheckNotInstalledInstallationState \
CheckZodbDocumentRemoved \
SaveBusinessTemplate \
CheckForkedMigrationExport \
'
sequence_list.addSequenceString(sequence_string)
# XXX-arnau: Temporary until _perform_migration is set to True by default
from Products.ERP5.Document.BusinessTemplate import DocumentTemplateItem
DocumentTemplateItem._perform_migration = True
try:
sequence_list.play(self)
finally:
DocumentTemplateItem._perform_migration = False
def test_BusinessTemplateUpdateWithDocument(self): def test_BusinessTemplateUpdateWithDocument(self):
sequence_list = SequenceList() sequence_list = SequenceList()
sequence_string = '\ sequence_string = '\
...@@ -6887,109 +6995,6 @@ class TestExtensionTemplateItem(TestDocumentTemplateItem): ...@@ -6887,109 +6995,6 @@ class TestExtensionTemplateItem(TestDocumentTemplateItem):
component_module = ExtensionComponent._getDynamicModuleNamespace() component_module = ExtensionComponent._getDynamicModuleNamespace()
component_portal_type = ExtensionComponent.portal_type component_portal_type = ExtensionComponent.portal_type
def getBusinessTemplateList(self):
return (super(TestExtensionTemplateItem, self).getBusinessTemplateList() +
('erp5_core_component',))
def stepCheckZodbDocumentRemoved(self, sequence=None, **kw):
component_tool = self.getPortalObject().portal_components
component_id = 'erp5.component.extension.' + sequence['document_title']
self.failIf(component_id in component_tool.objectIds())
def stepRemoveZodbDocument(self, sequence=None, **kw):
"""
Remove Property Sheet, but only from ZODB
"""
component_id = '%s.%s' % (self.component_module, sequence['document_title'])
self.portal.portal_components.manage_delObjects([component_id])
def stepCheckDocumentMigration(self, sequence=None, **kw):
"""
Check migration of Document from the Filesystem to ZODB
"""
component_id = '%s.%s' % (self.component_module, sequence['document_title'])
component_tool = self.getPortalObject().portal_components
self.failUnless(component_id in component_tool.objectIds())
component = getattr(component_tool, component_id)
self.assertEquals(component.getReference(), self.document_title)
self.assertEquals(component.getTextContent(), self.document_data)
self.assertEquals(component.getPortalType(), self.component_portal_type)
def stepCheckForkedMigrationExport(self, sequence=None, **kw):
component_bt_tool_path = os.path.join(sequence['template_path'],
'ExtensionTemplateItem',
'portal_components')
self.assertTrue(os.path.exists(component_bt_tool_path))
component_id = '%s.%s' % (self.component_module, sequence['document_title'])
base_path = os.path.join(component_bt_tool_path, component_id)
python_source_code_path = base_path + '.py'
self.assertTrue(os.path.exists(python_source_code_path))
source_code = sequence['document_data']
with open(python_source_code_path) as f:
self.assertEquals(f.read(), source_code)
xml_path = base_path + '.xml'
self.assertTrue(os.path.exists(xml_path))
first_line = source_code.split('\n', 1)[0]
with open(xml_path) as f:
for line in f:
self.failIf(first_line in line)
def test_BusinessTemplateWithDocumentMigration(self):
sequence_list = SequenceList()
sequence_string = '\
CreateDocument \
CreateNewBusinessTemplate \
UseExportBusinessTemplate \
AddDocumentToBusinessTemplate \
CheckModifiedBuildingState \
CheckNotInstalledInstallationState \
BuildBusinessTemplate \
CheckBuiltBuildingState \
CheckNotInstalledInstallationState \
CheckObjectPropertiesInBusinessTemplate \
SaveBusinessTemplate \
CheckBuiltBuildingState \
CheckNotInstalledInstallationState \
RemoveDocument \
RemoveBusinessTemplate \
RemoveAllTrashBins \
ImportBusinessTemplate \
UseImportBusinessTemplate \
CheckBuiltBuildingState \
CheckNotInstalledInstallationState \
InstallWithoutForceBusinessTemplate \
Tic \
CheckInstalledInstallationState \
CheckBuiltBuildingState \
CheckNoTrashBin \
CheckSkinsLayers \
CheckDocumentMigration \
CheckDocumentRemoved \
UninstallBusinessTemplate \
CheckBuiltBuildingState \
CheckNotInstalledInstallationState \
CheckZodbDocumentRemoved \
SaveBusinessTemplate \
CheckForkedMigrationExport \
'
sequence_list.addSequenceString(sequence_string)
# XXX-arnau: Temporary until _perform_migration is set to True by default
from Products.ERP5.Document.BusinessTemplate import ExtensionTemplateItem
ExtensionTemplateItem._perform_migration = True
try:
sequence_list.play(self)
finally:
ExtensionTemplateItem._perform_migration = False
class TestTestTemplateItem(TestDocumentTemplateItem): class TestTestTemplateItem(TestDocumentTemplateItem):
document_title = 'UnitTest' document_title = 'UnitTest'
document_data = """class UnitTest: document_data = """class UnitTest:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment