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

BusinessTemplate: update tools, except the one we know to be too big

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 skip
only portal_simulation, because we know that it will contain lots of
applied rules and portal_preferences, because we know it contain
user preferences.

Other candidates were:
 - portal_trash/portal_templates: contain lots of documents,
proportional to the number of business template updates, but is not
managed in business template (for bootstrap issues)
 - portal_activities: contain a lot of active processes, but is not
managed in business template
parent 41820141
Pipeline #10796 failed with stage
in 0 seconds
......@@ -5140,6 +5140,54 @@ 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",
title="Dummy Tool Version 1")
# 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()
self.assertEqual(self.portal.dummy_tool.getTitle(), "Dummy Tool Version 1")
self.portal.dummy_tool.setTitle("Dummy Tool Version 2")
bt.build()
self.tic()
# undo the change in title
self.portal.dummy_tool.setTitle("Dummy Tool Version 1")
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.getTitle(), "Dummy Tool Version 2")
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,7 +1813,20 @@ 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.
Also, some tools can contain lots of sub-documents, like for example
simulation tool which contain all applied rules, currently we are not
able to update them, because business template does support updating a
document with so many documents (that's why we special case ModuleTemplateItem).
But we want to update tools, so for now we don't have a better solution
then skipping some tools we know to be too big.
"""
_non_updateable_tool_id_set = set([
"portal_simulation",
"portal_preferences",
])
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,
......@@ -1823,14 +1836,15 @@ class ToolTemplateItem(PathTemplateItem):
object_dict = ObjectTemplateItem.preinstall(self, 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 action == 'New':
del object_dict[path]
elif action == 'Modified':
object_dict[path] = 'Modified but should be kept', type_name
elif action == 'Removed':
object_dict[path] = 'Removed but should be kept', type_name
if path in self._non_updateable_tool_id_set:
obj = getattr(portal_base, path, None)
if obj is not None:
if action == 'New':
del object_dict[path]
elif action == 'Modified':
object_dict[path] = 'Modified but should be kept', type_name
elif action == 'Removed':
object_dict[path] = 'Removed but should be kept', type_name
return object_dict
def install(self, context, trashbin, **kw):
......
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