Commit 81658fb8 authored by Arnaud Fontaine's avatar Arnaud Fontaine

Define versions and their priorities for ZODB Components on Business Template.

This is similar to portal skins priority, except that versions and priorities
are defined on ERP5Site (as 'VERSION | PRIORITY' where PRIORITY is a float) as
there is not one Folder for each version in contrary to portal skins.

On the Business Template itself, versions and priorities can be defined like
'VERSION | PRIORITY' or simply 'VERSION' (where PRIORITY is assumed to be
0.0). Upon installation, it will be merged into ERP5Site property in
descending order (by priority first and then by version for versions with the
same priority).
parent 272ac2f7
...@@ -1763,6 +1763,116 @@ class RegisteredSkinSelectionTemplateItem(BaseTemplateItem): ...@@ -1763,6 +1763,116 @@ class RegisteredSkinSelectionTemplateItem(BaseTemplateItem):
skin_selection_dict[skin_folder_id] = selection_list skin_selection_dict[skin_folder_id] = selection_list
self._objects = skin_selection_dict self._objects = skin_selection_dict
class RegisteredVersionPrioritySelectionTemplateItem(BaseTemplateItem):
def _fillObjectDictFromArchive(self):
for version_priority in self._archive:
try:
version, priority = version_priority.split('|')
priority = float(priority)
except ValueError:
version = version_priority
priority = 0.
self._objects[version.strip()] = priority
def build(self, context, **kw):
self._fillObjectDictFromArchive()
def install(self, context, trashbin, **kw):
if not self._objects:
return
portal = context.getPortalObject()
registered_tuple_list = []
for value in portal.getVersionPriorityList():
try:
version, priority = value.split('|')
priority = float(priority)
except ValueError:
version = value
priority = 0.
registered_tuple_list.append((version.strip(), priority))
update_dict = kw.get('object_to_update')
force = kw.get('force')
registered_name_list = set(portal.getVersionPriorityNameList())
for new_version, new_priority in self._objects.iteritems():
action = update_dict.get(new_version)
if (not action or action == 'nothing') and not force:
continue
# Merge version and priority defined on this bt and already registered
# version and priority
inserted = False
index = 0
for (version, priority) in registered_tuple_list:
if new_version == version:
if new_priority == priority:
inserted = True
break
else:
del registered_tuple_list[index]
continue
elif not inserted:
if new_priority > priority:
registered_tuple_list.insert(index, (new_version, new_priority))
inserted = True
elif new_priority == priority and new_version >= version:
registered_tuple_list.insert(index, (new_version, new_priority))
inserted = True
index += 1
if not inserted:
registered_tuple_list.append((new_version, new_priority))
portal.setVersionPriorityList(('%s | %s' % (version, priority)
for version, priority in registered_tuple_list))
def preinstall(self, context, installed_item, **kw):
if context.getTemplateFormatVersion() != 1:
return {}
modified_object_list = {}
class_name_prefix = self.__class__.__name__[:-12]
for path, new_object in self._objects.iteritems():
old_object = installed_item._objects.get(path)
if old_object is not None:
# Compare object to see it there is any change
if new_object != old_object:
modified_object_list.update({path : ['Modified', class_name_prefix]})
else:
modified_object_list.update({path : ['New', class_name_prefix]})
# Get removed objects
for path in installed_item._objects:
if path not in self._objects:
modified_object_list.update({path : ['Removed', class_name_prefix]})
return modified_object_list
def importFile(self, bta, **kw):
super(RegisteredVersionPrioritySelectionTemplateItem,
self).importFile(bta, **kw)
self._objects.clear()
self._fillObjectDictFromArchive()
def uninstall(self, context, **kw):
object_path = kw.get('object_path')
object_list = object_path and (object_path,) or self._objects
portal = context.getPortalObject()
registered_list = list(portal.getVersionPriorityList())
index = 0
for version in portal.getVersionPriorityNameList():
if version in object_list:
del registered_list[index]
else:
index += 1
portal.setVersionPriorityList(registered_list)
class WorkflowTemplateItem(ObjectTemplateItem): class WorkflowTemplateItem(ObjectTemplateItem):
...@@ -4565,6 +4675,7 @@ Business Template is a set of definitions, such as skins, portal types and categ ...@@ -4565,6 +4675,7 @@ Business Template is a set of definitions, such as skins, portal types and categ
# path and use it with SQLMethods in a skin. # path and use it with SQLMethods in a skin.
# ( and more ) # ( and more )
_item_name_list = [ _item_name_list = [
'_registered_version_priority_selection_item',
'_product_item', '_product_item',
'_document_item', '_document_item',
'_property_sheet_item', '_property_sheet_item',
...@@ -4674,6 +4785,9 @@ Business Template is a set of definitions, such as skins, portal types and categ ...@@ -4674,6 +4785,9 @@ Business Template is a set of definitions, such as skins, portal types and categ
self._registered_skin_selection_item = \ self._registered_skin_selection_item = \
RegisteredSkinSelectionTemplateItem( RegisteredSkinSelectionTemplateItem(
self.getTemplateRegisteredSkinSelectionList()) self.getTemplateRegisteredSkinSelectionList())
self._registered_version_priority_selection_item = \
RegisteredVersionPrioritySelectionTemplateItem(
self.getTemplateRegisteredVersionPrioritySelectionList())
self._category_item = \ self._category_item = \
CategoryTemplateItem(self.getTemplateBaseCategoryList()) CategoryTemplateItem(self.getTemplateBaseCategoryList())
self._catalog_method_item = \ self._catalog_method_item = \
...@@ -5224,6 +5338,13 @@ Business Template is a set of definitions, such as skins, portal types and categ ...@@ -5224,6 +5338,13 @@ Business Template is a set of definitions, such as skins, portal types and categ
""" """
return self._getOrderedList('template_registered_skin_selection') return self._getOrderedList('template_registered_skin_selection')
def getTemplateRegisteredVersionPrioritySelectionList(self):
"""
We have to set this method because we want an
ordered list
"""
return self._getOrderedList('template_registered_version_priority_selection')
def getTemplateModuleIdList(self): def getTemplateModuleIdList(self):
""" """
We have to set this method because we want an We have to set this method because we want an
......
...@@ -451,7 +451,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin): ...@@ -451,7 +451,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
""" """
# Whatever happens, a version must always be returned otherwise it may # Whatever happens, a version must always be returned otherwise it may
# render the site unusable when all Products will have been migrated # render the site unusable when all Products will have been migrated
return self._version_priority_list or ('erp5',) return self._version_priority_list or ('erp5 | 0.0',)
security.declareProtected(Permissions.ModifyPortalContent, security.declareProtected(Permissions.ModifyPortalContent,
'setVersionPriorityList' ) 'setVersionPriorityList' )
...@@ -460,6 +460,9 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin): ...@@ -460,6 +460,9 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
XXX-arnau: must be written through an interaction workflow when ERP5Site XXX-arnau: must be written through an interaction workflow when ERP5Site
will become a real ERP5 object... will become a real ERP5 object...
""" """
if not isinstance(value, tuple):
value = tuple(value)
self._version_priority_list = value self._version_priority_list = value
if not getattr(self, '_v_bootstrapping', False): if not getattr(self, '_v_bootstrapping', False):
...@@ -468,6 +471,12 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin): ...@@ -468,6 +471,12 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
version_priority_list = property(getVersionPriorityList, version_priority_list = property(getVersionPriorityList,
setVersionPriorityList) setVersionPriorityList)
security.declarePrivate('getVersionPriorityNameList')
def getVersionPriorityNameList(self):
# XXX-arnau: should be cached?
return [name.split('|')[0].strip()
for name in self.getVersionPriorityList()]
security.declareProtected(Permissions.AccessContentsInformation, 'getUid') security.declareProtected(Permissions.AccessContentsInformation, 'getUid')
def getUid(self): def getUid(self):
""" """
...@@ -1696,7 +1705,7 @@ class ERP5Generator(PortalGenerator): ...@@ -1696,7 +1705,7 @@ class ERP5Generator(PortalGenerator):
# Return the fully wrapped object. # Return the fully wrapped object.
p = parent.this()._getOb(id) p = parent.this()._getOb(id)
p._setProperty('version_priority_list', ('erp5',), 'lines') p._setProperty('version_priority_list', ('erp5 | 0.0',), 'lines')
erp5_sql_deferred_connection_string = erp5_sql_connection_string erp5_sql_deferred_connection_string = erp5_sql_connection_string
p._setProperty('erp5_catalog_storage', p._setProperty('erp5_catalog_storage',
......
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
<list> <list>
<string>my_template_module_id_list</string> <string>my_template_module_id_list</string>
<string>my_template_base_category_list</string> <string>my_template_base_category_list</string>
<string>my_template_registered_version_priority_selection_list</string>
</list> </list>
</value> </value>
</item> </item>
......
...@@ -123,7 +123,7 @@ ...@@ -123,7 +123,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>_text</string> </key> <key> <string>_text</string> </key>
<value> <string>python: [(v, v) for v in here.getPortalObject().getVersionPriorityList()]</string> </value> <value> <string>python: [(v, v) for v in here.getPortalObject().getVersionPriorityNameList()]</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -108,7 +108,7 @@ ...@@ -108,7 +108,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>_text</string> </key> <key> <string>_text</string> </key>
<value> <string>python: here.getPortalObject().getVersionPriorityList()</string> </value> <value> <string>python: here.getPortalObject().getVersionPriorityNameList()</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
2012-03-06 arnaud.fontaine
* Add registered version priority selection on BusinessTemplate_view for registering version priority of ZODB Components only for now.
2012-03-05 arnaud.fontaine 2012-03-05 arnaud.fontaine
* Allow to run ZODB Test Component tests from Component Tool, likewise Class Tool. * Allow to run ZODB Test Component tests from Component Tool, likewise Class Tool.
......
41026 41027
\ No newline at end of file \ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/lines</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>A list of registered version priority used by this template</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>template_registered_version_priority_selection_property</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>property_default</string> </key>
<value> <string>python: ()</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
2012-03-06 arnaud.fontaine
* Add template_registered_version_priority_selection property to BusinessTemplate to define version and their priorities for ZODB Component only for now.
2011-12-15 yusei 2011-12-15 yusei
* Fix ProductionOrderLine.resource_category_existence. Any resource type document is ok to be used as resource on production order line. * Fix ProductionOrderLine.resource_category_existence. Any resource type document is ok to be used as resource on production order line.
......
46 47
\ No newline at end of file \ No newline at end of file
...@@ -6565,6 +6565,99 @@ class TestBusinessTemplate(BusinessTemplateMixin): ...@@ -6565,6 +6565,99 @@ class TestBusinessTemplate(BusinessTemplateMixin):
sequence_list.addSequenceString(sequence_string) sequence_list.addSequenceString(sequence_string)
sequence_list.play(self) sequence_list.play(self)
def stepSetVersionPriorityRegisteredSelection(self, sequence=None, **kw):
bt = sequence.get('current_bt')
self.failIf(bt is None)
version_priority_list = ('abc| 1.0',
'def |99.0',
'erp4')
bt.edit(template_registered_version_priority_selection_list=version_priority_list)
sequence.edit(expected_version_priority_list=('def | 99.0',
'abc | 1.0',
'erp5 | 0.0',
'erp4 | 0.0'),
current_bt_version_priority_list=tuple(sorted(version_priority_list)))
def stepUpdateVersionPriorityRegisteredSelection(self, sequence=None, **kw):
bt = sequence.get('current_bt')
self.failIf(bt is None)
version_priority_list = ('erp4',
'abc | 1.0',
'foo | 2.0',
'bar | 100.0')
bt.edit(template_registered_version_priority_selection_list=version_priority_list)
sequence.edit(expected_version_priority_list=('bar | 100.0',
'foo | 2.0',
'abc | 1.0',
'erp5 | 0.0',
'erp4 | 0.0'),
current_bt_version_priority_list=tuple(sorted(version_priority_list)))
def stepCheckVersionPriorityRegisteredSelection(self, sequence=None, **kw):
bt = sequence.get('current_bt')
self.assertEqual(tuple(bt.getTemplateRegisteredVersionPrioritySelectionList()),
sequence['current_bt_version_priority_list'])
def stepRemoveVersionPriorityRegisteredSelectionBeforeImport(self,
sequence=None,
**kw):
bt = sequence.get('current_bt')
bt.edit(template_registered_version_priority_selection_list=())
def stepCheckVersionPrioritySetOnSite(self, sequence=None, **kw):
bt = sequence.get('current_bt')
self.assertEqual(self.getPortalObject().getVersionPriorityList(),
sequence['expected_version_priority_list'])
def stepCheckVersionPriorityRemovedFromSite(self, sequence=None, **kw):
bt = sequence.get('current_bt')
self.assertEqual(self.getPortalObject().getVersionPriorityList(),
('erp5 | 0.0',))
def stepRemoveVersionPriorityRegisteredSelection(self, sequence=None, **kw):
bt = sequence.get('current_bt')
bt.edit(template_registered_version_priority_selection=())
sequence.edit(expected_version_priority_list=('erp5 | 0.0'),
current_bt_version_priority_list=())
def test_BusinessTemplateWithVersionPrioritySelection(self):
sequence_list = SequenceList()
sequence_string = 'CreateNewBusinessTemplate \
UseExportBusinessTemplate \
SetVersionPriorityRegisteredSelection \
BuildBusinessTemplate \
SaveBusinessTemplate \
RemoveVersionPriorityRegisteredSelectionBeforeImport \
ImportBusinessTemplate \
UseImportBusinessTemplate \
CheckVersionPriorityRegisteredSelection \
InstallWithoutForceBusinessTemplate \
Tic \
CheckVersionPrioritySetOnSite \
UninstallBusinessTemplate \
Tic \
CheckVersionPriorityRemovedFromSite \
\
UpdateVersionPriorityRegisteredSelection \
BuildBusinessTemplate \
CheckVersionPriorityRegisteredSelection \
InstallWithoutForceBusinessTemplate \
Tic \
CheckVersionPrioritySetOnSite \
UninstallBusinessTemplate \
Tic \
CheckVersionPriorityRemovedFromSite \
'
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
class TestDocumentTemplateItem(BusinessTemplateMixin): class TestDocumentTemplateItem(BusinessTemplateMixin):
......
...@@ -104,7 +104,7 @@ class ComponentDynamicPackage(ModuleType): ...@@ -104,7 +104,7 @@ class ComponentDynamicPackage(ModuleType):
except AttributeError: except AttributeError:
return {} return {}
version_priority_set = set(portal.getVersionPriorityList()) version_priority_set = set(portal.getVersionPriorityNameList())
# objectValues should not be used for a large number of objects, but # objectValues should not be used for a large number of objects, but
# this is only done at startup or upon reset, moreover using the Catalog # this is only done at startup or upon reset, moreover using the Catalog
...@@ -154,7 +154,7 @@ class ComponentDynamicPackage(ModuleType): ...@@ -154,7 +154,7 @@ class ComponentDynamicPackage(ModuleType):
# wrongly considered as importable and thus the actual filesystem class # wrongly considered as importable and thus the actual filesystem class
# ignored # ignored
elif (name not in self._registry_dict and elif (name not in self._registry_dict and
name[:-self.__version_suffix_len] not in site.getVersionPriorityList()): name[:-self.__version_suffix_len] not in site.getVersionPriorityNameList()):
return None return None
return self return self
...@@ -181,7 +181,7 @@ class ComponentDynamicPackage(ModuleType): ...@@ -181,7 +181,7 @@ class ComponentDynamicPackage(ModuleType):
component_name = fullname[len(self._namespace_prefix):] component_name = fullname[len(self._namespace_prefix):]
if component_name.endswith('_version'): if component_name.endswith('_version'):
version = component_name[:-self.__version_suffix_len] version = component_name[:-self.__version_suffix_len]
return (version in site.getVersionPriorityList() and return (version in site.getVersionPriorityNameList() and
self._getVersionPackage(version) or None) self._getVersionPackage(version) or None)
component_id_alias = None component_id_alias = None
...@@ -207,7 +207,7 @@ class ComponentDynamicPackage(ModuleType): ...@@ -207,7 +207,7 @@ class ComponentDynamicPackage(ModuleType):
raise ImportError("%s: Component %s could not be found" % (fullname, raise ImportError("%s: Component %s could not be found" % (fullname,
component_name)) component_name))
for version in site.getVersionPriorityList(): for version in site.getVersionPriorityNameList():
component = component_version_dict.get(version) component = component_version_dict.get(version)
if component is not None: if component is not None:
break break
......
...@@ -1596,7 +1596,7 @@ def bar(*args, **kwargs): ...@@ -1596,7 +1596,7 @@ def bar(*args, **kwargs):
ComponentTool.reset = assertResetCalled ComponentTool.reset = assertResetCalled
priority_tuple = site.getVersionPriorityList() priority_tuple = site.getVersionPriorityList()
try: try:
site.setVersionPriorityList(('foo',) + priority_tuple) site.setVersionPriorityList(('foo | 99.0',) + priority_tuple)
transaction.commit() transaction.commit()
self.tic() self.tic()
......
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