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

accessor_holder: respect the order of property_sheets when building class

Because this was using a set, the order in which property sheets were
used when generating classes was not deterministic.
This can make a different if two property sheets define the same
property. This was the case for short_title property, which was defined
with different default values in DublinCore and SimpleItem property
sheets. With this change the behavior is always same when hash
randomization is enabled.

Property sheets can be defined in classes or on the portal type. The
test only covers the case that a property defined on the portal type
must override the same property defined on a class, but the expected
behavior is also that property sheets defined on a class override
property sheets from parent class.
parent bfc4f46e
...@@ -2393,6 +2393,18 @@ class TestERP5Type(PropertySheetTestCase, LogInterceptor): ...@@ -2393,6 +2393,18 @@ class TestERP5Type(PropertySheetTestCase, LogInterceptor):
self.assertEqual('Could not get object region/gamma', self.assertEqual('Could not get object region/gamma',
logged_errors[0].getMessage()) logged_errors[0].getMessage())
def test_portal_type_property_sheet_have_priority_over_class_property_sheet(self):
self._addProperty(
'Person',
self.id(),
'first_name',
elementary_type='string',
property_default='string:property sheet default',
portal_type='Standard Property',
)
obj = self.getPersonModule().newContent(portal_type='Person')
self.assertEqual(obj.getFirstName(), 'property sheet default')
def test_list_accessors(self): def test_list_accessors(self):
self._addProperty('Person', 'test_list_accessors', 'dummy', self._addProperty('Person', 'test_list_accessors', 'dummy',
elementary_type='lines', elementary_type='lines',
......
...@@ -33,6 +33,7 @@ Accessor Holders, that is, generation of methods for ERP5 ...@@ -33,6 +33,7 @@ Accessor Holders, that is, generation of methods for ERP5
* Utils, Property Sheet Tool can be probably be cleaned up as well by * Utils, Property Sheet Tool can be probably be cleaned up as well by
moving specialized code here. moving specialized code here.
""" """
import collections
from six import string_types as basestring from six import string_types as basestring
from types import ModuleType from types import ModuleType
...@@ -342,7 +343,7 @@ def applyCategoryAsRelatedValueAccessor(accessor_holder, ...@@ -342,7 +343,7 @@ def applyCategoryAsRelatedValueAccessor(accessor_holder,
accessor = accessor_class(accessor_name % uppercase_category_id, category_id) accessor = accessor_class(accessor_name % uppercase_category_id, category_id)
accessor_holder.registerAccessor(accessor, read_permission) accessor_holder.registerAccessor(accessor, read_permission)
def getPropertySheetValueList(site, property_sheet_name_set): def getPropertySheetValueList(site, property_sheet_name_list):
try: try:
property_sheet_tool = site.portal_property_sheets property_sheet_tool = site.portal_property_sheets
...@@ -356,7 +357,7 @@ def getPropertySheetValueList(site, property_sheet_name_set): ...@@ -356,7 +357,7 @@ def getPropertySheetValueList(site, property_sheet_name_set):
property_sheet_value_list = [] property_sheet_value_list = []
for property_sheet_name in property_sheet_name_set: for property_sheet_name in property_sheet_name_list:
try: try:
property_sheet = property_sheet_tool._getOb(property_sheet_name) property_sheet = property_sheet_tool._getOb(property_sheet_name)
except (AttributeError, KeyError): except (AttributeError, KeyError):
...@@ -420,7 +421,10 @@ def createAllAccessorHolderList(site, ...@@ -420,7 +421,10 @@ def createAllAccessorHolderList(site,
""" """
from erp5 import accessor_holder as accessor_holder_module from erp5 import accessor_holder as accessor_holder_module
property_sheet_name_set = set() # Use an ordered dict as a set keeping the order, to generate the list
# of accessor holders that will be the bases of the portal type class
# in the same order as the property sheets defined in the class hierarchy.
property_sheet_name_set = collections.OrderedDict()
accessor_holder_list = [] accessor_holder_list = []
# Get the accessor holders of the Portal Type # Get the accessor holders of the Portal Type
...@@ -456,7 +460,7 @@ def createAllAccessorHolderList(site, ...@@ -456,7 +460,7 @@ def createAllAccessorHolderList(site,
else: else:
for property_sheet in zodb_property_sheet_name_set: for property_sheet in zodb_property_sheet_name_set:
if property_sheet.endswith('Preference'): if property_sheet.endswith('Preference'):
property_sheet_name_set.add(property_sheet) property_sheet_name_set[property_sheet] = None
# XXX a hook to add per-portal type accessor holders maybe? # XXX a hook to add per-portal type accessor holders maybe?
if portal_type_name == "Preference Tool": if portal_type_name == "Preference Tool":
...@@ -479,15 +483,15 @@ def createAllAccessorHolderList(site, ...@@ -479,15 +483,15 @@ def createAllAccessorHolderList(site,
if not isinstance(property_sheet, basestring): if not isinstance(property_sheet, basestring):
property_sheet = property_sheet.__name__ property_sheet = property_sheet.__name__
property_sheet_name_set.add(property_sheet) property_sheet_name_set[property_sheet] = None
property_sheet_name_set = property_sheet_name_set - \ property_sheet_value_list = getPropertySheetValueList(
portal_type_property_sheet_name_set site,
[ps for ps in property_sheet_name_set
if ps not in portal_type_property_sheet_name_set])
document_accessor_holder_list = \ document_accessor_holder_list = \
getAccessorHolderList(site, portal_type_name, getAccessorHolderList(site, portal_type_name, property_sheet_value_list)
getPropertySheetValueList(site,
property_sheet_name_set))
accessor_holder_list.extend(document_accessor_holder_list) accessor_holder_list.extend(document_accessor_holder_list)
......
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