Commit 7d0ba519 authored by Julien Muchembled's avatar Julien Muchembled

Fix support for default values in preferences when several preferences are active

Also fix testPreferences and set default value for
preferred_accounting_transaction_simulation_state property.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@29345 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 1d6f5aa1
...@@ -48,6 +48,7 @@ class AccountingPreference: ...@@ -48,6 +48,7 @@ class AccountingPreference:
'description' : 'The simulation state for transactions', 'description' : 'The simulation state for transactions',
'type' : 'tokens', 'type' : 'tokens',
'preference' : 1, 'preference' : 1,
'default' : [],
'mode' : 'w'}, 'mode' : 'w'},
{ 'id' : 'preferred_accounting_transaction_section_category', { 'id' : 'preferred_accounting_transaction_section_category',
'description' : 'The section category for transactions; '\ 'description' : 'The section category for transactions; '\
......
...@@ -40,7 +40,7 @@ from Products.ERP5Type.Accessor.TypeDefinition import list_types ...@@ -40,7 +40,7 @@ from Products.ERP5Type.Accessor.TypeDefinition import list_types
from Products.ERP5Form import _dtmldir from Products.ERP5Form import _dtmldir
from Products.ERP5Form.Document.Preference import Priority from Products.ERP5Form.Document.Preference import Priority
_marker = [] _marker = object()
def updatePreferenceClassPropertySheetList(): def updatePreferenceClassPropertySheetList():
# The Preference class should be imported from the common location # The Preference class should be imported from the common location
...@@ -104,7 +104,7 @@ def createPreferenceToolAccessorList(portal) : ...@@ -104,7 +104,7 @@ def createPreferenceToolAccessorList(portal) :
if prop['type'] in list_types : if prop['type'] in list_types :
attr_list += ['get%sList' % convertToUpperCase(attribute), ] attr_list += ['get%sList' % convertToUpperCase(attribute), ]
for attribute_name in attr_list: for attribute_name in attr_list:
method = PreferenceMethod(attribute_name) method = PreferenceMethod(attribute_name, prop.get('default'))
setattr(PreferenceTool, attribute_name, method) setattr(PreferenceTool, attribute_name, method)
...@@ -118,46 +118,35 @@ class PreferenceMethod(Method): ...@@ -118,46 +118,35 @@ class PreferenceMethod(Method):
func_code.co_argcount = 1 func_code.co_argcount = 1
func_defaults = () func_defaults = ()
def __init__(self, attribute): def __init__(self, attribute, default):
self._preference_name = attribute self._preference_getter = attribute
self._preference_default = default
self._preference_cache_id = 'PreferenceTool.CachingMethod.%s' % attribute self._preference_cache_id = 'PreferenceTool.CachingMethod.%s' % attribute
self._null = (None, '', (), [])
def __call__(self, instance, *args, **kw): def __call__(self, instance, default=_marker, *args, **kw):
def _getPreference(*args, **kw): def _getPreference(*args, **kw):
value = None
# XXX: sql_catalog_id is passed when calling getPreferredArchive # XXX: sql_catalog_id is passed when calling getPreferredArchive
# This is inconsistent with regular accessor API, and indicates that # This is inconsistent with regular accessor API, and indicates that
# there is a design problem in current archive API. # there is a design problem in current archive API.
sql_catalog_id = kw.pop('sql_catalog_id', None) sql_catalog_id = kw.pop('sql_catalog_id', None)
for pref in instance._getSortedPreferenceList(sql_catalog_id=sql_catalog_id): for pref in instance._getSortedPreferenceList(sql_catalog_id=sql_catalog_id):
value = getattr(pref, self._preference_name, _marker) value = getattr(pref, self._preference_getter)(_marker, *args, **kw)
# XXX-JPS Why don't we use accessors here such as: # XXX Due to UI limitation, null value is treated as if the property
# value = pref.getProperty(self._preference_name, _marker) # was not defined. The drawback is that it is not possible for a
if value is not _marker: # user to mask a non-null global value with a null value.
# If callable, store the return value. if value not in (_marker, None, '', (), []):
if callable(value): return value
value = value(*args, **kw) return _marker
if value not in self._null:
break
return value
_getPreference = CachingMethod(_getPreference, _getPreference = CachingMethod(_getPreference,
id='%s.%s' % (self._preference_cache_id, id='%s.%s' % (self._preference_cache_id,
getSecurityManager().getUser().getId()), getSecurityManager().getUser().getId()),
cache_factory='erp5_ui_short') cache_factory='erp5_ui_short')
value = _getPreference(*args, **kw) value = _getPreference(*args, **kw)
# XXX Preference Tool has a strange assumption that, even if if value is not _marker:
# all values are null values, one of them must be returned. return value
# Therefore, return a default value, only if explicitly specified, elif default is _marker:
# instead of returning None. return self._preference_default
default = _marker return default
if 'default' in kw:
default = kw['default']
elif args:
default = args[0]
if value in self._null and default is not _marker:
return default
return value
class PreferenceTool(BaseTool): class PreferenceTool(BaseTool):
""" """
...@@ -199,11 +188,7 @@ class PreferenceTool(BaseTool): ...@@ -199,11 +188,7 @@ class PreferenceTool(BaseTool):
""" get the preference on the most appopriate Preference object. """ """ get the preference on the most appopriate Preference object. """
method = getattr(self, 'get%s' % convertToUpperCase(pref_name), None) method = getattr(self, 'get%s' % convertToUpperCase(pref_name), None)
if method is not None: if method is not None:
if default is not _marker: return method(default)
kw = {'default': default}
else:
kw = {}
return method(**kw)
return default return default
security.declareProtected(Permissions.ModifyPortalContent, "setPreference") security.declareProtected(Permissions.ModifyPortalContent, "setPreference")
......
...@@ -39,6 +39,11 @@ from DateTime import DateTime ...@@ -39,6 +39,11 @@ from DateTime import DateTime
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.ERP5Form.Document.Preference import Priority from Products.ERP5Form.Document.Preference import Priority
from Products.ERP5.PropertySheet.HtmlStylePreference import HtmlStylePreference
default_large_image_height, = [pref.get('default')
for pref in HtmlStylePreference._properties
if pref['id'] == 'preferred_large_image_height']
class TestPreferences(ERP5TypeTestCase): class TestPreferences(ERP5TypeTestCase):
...@@ -367,26 +372,27 @@ class TestPreferences(ERP5TypeTestCase): ...@@ -367,26 +372,27 @@ class TestPreferences(ERP5TypeTestCase):
method = pref_tool.getPreferredAccountingTransactionSimulationState method = pref_tool.getPreferredAccountingTransactionSimulationState
state = method() state = method()
self.assertEquals(state, None) self.assertEquals(state, [])
state = method('default') state = method('default')
self.assertEquals(state, 'default') self.assertEquals(state, 'default')
method = lambda *args: pref_tool.getPreference('preferred_accounting_transaction_simulation_state', *args) method = lambda *args: pref_tool.getPreference('preferred_accounting_transaction_simulation_state', *args)
state = method() state = method()
self.assertEquals(state, None) self.assertEquals(state, [])
state = method('default') state = method('default')
self.assertEquals(state, 'default') self.assertEquals(state, 'default')
method = pref_tool.getPreferredAccountingTransactionSimulationStateList method = pref_tool.getPreferredAccountingTransactionSimulationStateList
state_list = method() state_list = method()
self.assertEquals(state_list, None) self.assertEquals(state_list, [])
state_list = method(('default',)) state_list = method(('default',))
self.assertEquals(state_list, ['default',]) # getPreferredAccountingTransactionSimulationStateList # Initially, tuples were always casted to lists. This is not the case
# always tries to cast tuples to lists # anymore when preference_tool.getXxxList returns the default value.
self.assertEquals(state_list, ('default',))
method = lambda *args: pref_tool.getPreference('preferred_accounting_transaction_simulation_state_list', *args) method = lambda *args: pref_tool.getPreference('preferred_accounting_transaction_simulation_state_list', *args)
state_list = method() state_list = method()
self.assertEquals(state_list, None) self.assertEquals(state_list, [])
state_list = method(('default',)) state_list = method(('default',))
self.assertEquals(state_list, ('default',)) self.assertEquals(state_list, ('default',))
...@@ -424,21 +430,33 @@ class TestPreferences(ERP5TypeTestCase): ...@@ -424,21 +430,33 @@ class TestPreferences(ERP5TypeTestCase):
def test_SystemPreference(self): def test_SystemPreference(self):
# We want to test a property with a default value defined
self.assertTrue(default_large_image_height > 0)
large_image_height = default_large_image_height + 1
preference_tool = self.portal.portal_preferences preference_tool = self.portal.portal_preferences
site_pref = preference_tool.newContent( system_pref = preference_tool.newContent(
portal_type='System Preference', portal_type='System Preference',
preferred_accounting_transaction_simulation_state_list="this_is_default", preferred_ooodoc_server_address='127.0.0.1',
priority=Priority.SITE) priority=Priority.SITE)
# check not taken into account if not enabled # check not taken into account if not enabled
self.assertEquals(None, self.assertEqual(None,
preference_tool.getPreferredAccountingTransactionSimulationStateList()) preference_tool.getPreferredOoodocServerAddress())
self.assertEqual('localhost',
preference_tool.getPreferredOoodocServerAddress('localhost'))
self.assertEqual(default_large_image_height,
preference_tool.getPreferredLargeImageHeight())
# enable it and check preference is returned # enable it and check preference is returned
self.portal.portal_workflow.doActionFor(site_pref, 'enable_action') self.portal.portal_workflow.doActionFor(system_pref, 'enable_action')
self.assertEquals(site_pref.getPreferenceState(), 'global') self.assertEqual(system_pref.getPreferenceState(), 'global')
transaction.commit() transaction.commit()
self.tic() self.tic()
self.assertEquals(['this_is_default'], self.assertEqual('127.0.0.1',
preference_tool.getPreferredAccountingTransactionSimulationStateList()) preference_tool.getPreferredOoodocServerAddress())
self.assertEqual('127.0.0.1',
preference_tool.getPreferredOoodocServerAddress('localhost'))
self.assertEqual(default_large_image_height,
preference_tool.getPreferredLargeImageHeight())
# Members can't add new system preferences # Members can't add new system preferences
uf = self.getPortal().acl_users uf = self.getPortal().acl_users
...@@ -447,40 +465,39 @@ class TestPreferences(ERP5TypeTestCase): ...@@ -447,40 +465,39 @@ class TestPreferences(ERP5TypeTestCase):
newSecurityManager(None, member) newSecurityManager(None, member)
self.assertRaises(Unauthorized, preference_tool.newContent, portal_type='System Preference') self.assertRaises(Unauthorized, preference_tool.newContent, portal_type='System Preference')
# But they can see others # But they can see others
site_pref.view() system_pref.view()
# check accessors works # check accessors works
site_pref.setPreferredAccountingTransactionSimulationStateList( system_pref.setPreferredOoodocServerAddress('1.2.3.4')
['this_is_system'])
transaction.commit() transaction.commit()
self.tic() self.tic()
self.assertEquals(['this_is_system'], self.assertEqual('1.2.3.4',
preference_tool.getPreferredAccountingTransactionSimulationStateList()) preference_tool.getPreferredOoodocServerAddress())
self.assertEqual('1.2.3.4',
preference_tool.getPreferredOoodocServerAddress('localhost'))
self.assertEqual(default_large_image_height,
preference_tool.getPreferredLargeImageHeight())
# create a user pref and check it doesn't outranks the system one if # create a user pref and check it doesn't outranks the system one if
# they both defined same pref # they both defined same pref
user_pref = preference_tool.newContent( user_pref = preference_tool.newContent(
portal_type='Preference', portal_type='Preference',
priority=Priority.USER) priority=Priority.USER)
user_pref.setPreferredAccountingTransactionSimulationStateList( user_pref.setPreferredLargeImageHeight(large_image_height)
['this_is_user'])
self.portal.portal_workflow.doActionFor(user_pref, 'enable_action') self.portal.portal_workflow.doActionFor(user_pref, 'enable_action')
self.assertEquals(user_pref.getPreferenceState(), 'enabled') self.assertEqual(user_pref.getPreferenceState(), 'enabled')
transaction.commit() transaction.commit()
self.tic() self.tic()
self.assertEquals(['this_is_user'], self.assertEqual('1.2.3.4',
user_pref.getPreferredAccountingTransactionSimulationStateList()) preference_tool.getPreferredOoodocServerAddress('localhost'))
self.assertEquals(['this_is_system'], self.assertEqual(large_image_height,
preference_tool.getPreferredAccountingTransactionSimulationStateList()) preference_tool.getPreferredLargeImageHeight())
# check a user can't edit preference which are marked for manager (only for zope2.8) # check a user can't edit preference which are marked for manager
try: self.assertRaises(Unauthorized, user_pref.edit, preferred_ooodoc_server_address="localhost")
from ZODB.Transaction import Transaction
except ImportError:
self.assertRaises(Unauthorized, user_pref.edit, preferred_ooodoc_server_address="localhost")
# even if there is System Preference enabled getActivePreference shall return # even if there is System Preference enabled getActivePreference shall return
# user preference # user preference
self.assertEqual(user_pref, preference_tool.getActivePreference()) self.assertEqual(user_pref, preference_tool.getActivePreference())
self.assertEqual(site_pref, preference_tool.getActiveSystemPreference()) self.assertEqual(system_pref, preference_tool.getActiveSystemPreference())
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
......
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