Commit a52c7d5d authored by Jérome Perrin's avatar Jérome Perrin

BusinessTemplate: update tools, except legacy tools

Since 248f59e5 (Business Template: Likewise ERP5Site.addERP5Tool(), do
not re-create Tool if it already exists., 2020-06-22) we no longer
update tools, because of the problem that business template does not
currently handle updating objects with lots of sub-objects.

But we realized that we really need to update tools when they contain
configuration as object attributes, like mimetypes_registry, where the
problem was observed.

Instead of unconditionnally skipping any tool during update, we only
skip the ones that were initially managed by ERP5Generator and are moved
to business templates.
parent 18484163
......@@ -5140,6 +5140,56 @@ class TestBusinessTemplate(BusinessTemplateMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def test_tool_update(self):
self.portal.newContent(
id='dummy_tool',
portal_type="Alarm Tool")
# export and install a first version
bt = self.portal.portal_templates.newContent(
portal_type='Business Template',
title='test_bt_%s' % self.id(),
template_tool_id_list=('dummy_tool', ))
self.tic()
bt.build()
self.tic()
self.portal.manage_delObjects(ids=['dummy_tool'])
self.commit()
export_dir = tempfile.mkdtemp()
try:
bt.export(path=export_dir, local=True)
self.tic()
self.portal.portal_templates.updateBusinessTemplateFromUrl(
download_url='file:/%s' % export_dir)
finally:
shutil.rmtree(export_dir)
self.tic()
# build a new version of this business template, where the tool export some
# configuration (as some plain object attributes). In this case, we expect
# that updating the business template will set this configuration on the tool.
self.portal.dummy_tool._some_configuration = "saved in business template"
bt.build()
self.tic()
# undo the change in title
del self.portal.dummy_tool._some_configuration
export_dir = tempfile.mkdtemp()
try:
bt.export(path=export_dir, local=True)
self.tic()
new_bt = self.portal.portal_templates.updateBusinessTemplateFromUrl(
download_url='file:/%s' % export_dir)
finally:
shutil.rmtree(export_dir)
try:
self.assertEqual(self.portal.dummy_tool._some_configuration, "saved in business template")
finally:
new_bt.uninstall()
self.assertIsNone(self.portal._getOb('dummy_tool', None))
def test_21_CategoryIncludeSubobjects(self):
"""Test Category includes subobjects"""
sequence_list = SequenceList()
......
......@@ -1813,18 +1813,43 @@ class PathTemplateItem(ObjectTemplateItem):
class ToolTemplateItem(PathTemplateItem):
"""This class is used only for making a distinction between other objects
and tools, because tools may not be backed up."""
and tools, because tools may not be backed up.
We also have an exception for tools that were historically not managed in business
template but created by ERP5Generator at site creation. We don't update these tools
if they are already present, because they contain lots of sub-documents and are in
broken state before update (because their class was also moved to portal_components at
the same time). XXX The semantics of Tool vs Module are not really clear here - we
are also considering using ModuleTemplateItem for these.
"""
# Tools that were managed by ERP5Generator
_legacy_tool_id_list = set((
'portal_rules',
'portal_simulation',
'portal_deliveries',
'portal_orders',
'portal_ids',
'portal_domains',
'portal_tests',
'portal_password',
'portal_introspections',
'portal_acknowledgements',
))
def _backupObject(self, action, trashbin, container_path, object_id, **kw):
"""Fake as if a trashbin is not available."""
return PathTemplateItem._backupObject(self, action, None, container_path,
return super(ToolTemplateItem, self)._backupObject(action, None, container_path,
object_id, **kw)
def preinstall(self, context, installed_item, **kw):
object_dict = ObjectTemplateItem.preinstall(self, context, installed_item, **kw)
"""Don't install/update the tool if it's a legacy tool that was never updated.
"""
object_dict = super(ToolTemplateItem, self).preinstall(context, installed_item, **kw)
portal_base = aq_base(context.getPortalObject())
for path, (action, type_name) in object_dict.items():
obj = getattr(portal_base, path, None)
if obj is not None:
if obj is not None and path in self._legacy_tool_id_list:
if action == 'New':
del object_dict[path]
elif action == 'Modified':
......
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