[Erp5-report] r39348 arnaud.fontaine - in /erp5/trunk/products/ERP5Type: Core/ Dynamic/ Tool/
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Oct 19 16:36:05 CEST 2010
Author: arnaud.fontaine
Date: Tue Oct 19 16:36:04 2010
New Revision: 39348
URL: http://svn.erp5.org?rev=39348&view=rev
Log:
Implement constraints for ZODB Property Sheets and generate accessor
holder classes for filesystem Property Sheets too.
Added:
erp5/trunk/products/ERP5Type/Core/CategoryExistenceConstraint.py
- copied, changed from r39011, erp5/trunk/products/ERP5Type/Constraint/CategoryExistence.py
erp5/trunk/products/ERP5Type/Core/Constraint.py
- copied, changed from r39011, erp5/trunk/products/ERP5Type/Constraint/Constraint.py
erp5/trunk/products/ERP5Type/Core/PropertyExistenceConstraint.py
- copied, changed from r39011, erp5/trunk/products/ERP5Type/Constraint/PropertyExistence.py
Modified:
erp5/trunk/products/ERP5Type/Dynamic/portaltypeclass.py
erp5/trunk/products/ERP5Type/Tool/PropertySheetTool.py
Copied: erp5/trunk/products/ERP5Type/Core/CategoryExistenceConstraint.py (from r39011, erp5/trunk/products/ERP5Type/Constraint/CategoryExistence.py)
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Core/CategoryExistenceConstraint.py?p2=erp5/trunk/products/ERP5Type/Core/CategoryExistenceConstraint.py&p1=erp5/trunk/products/ERP5Type/Constraint/CategoryExistence.py&r1=39011&r2=39348&rev=39348&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/Constraint/CategoryExistence.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/Core/CategoryExistenceConstraint.py [utf8] Tue Oct 19 16:36:04 2010
@@ -1,8 +1,9 @@
##############################################################################
#
-# Copyright (c) 2002, 2005 Nexedi SARL and Contributors. All Rights Reserved.
-# Sebastien Robin <seb at nexedi.com>
-# Romain Courteaud <romain at nexedi.com>
+# Copyright (c) 2002-2010 Nexedi SARL and Contributors. All Rights Reserved.
+# Sebastien Robin <seb at nexedi.com>
+# Romain Courteaud <romain at nexedi.com>
+# Arnaud Fontaine <arnaud.fontaine at nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
@@ -27,21 +28,23 @@
#
##############################################################################
-from Constraint import Constraint
+from Products.ERP5Type.Core.Constraint import Constraint
+from AccessControl import ClassSecurityInfo
+from Products.ERP5Type import Permissions
-class CategoryExistence(Constraint):
- """This constraint checks if an object respects the existence of
- a category, without acquisition.
-
- Configuration example:
- { 'id' : 'category_existence',
- 'description' : 'Category causality must be defined',
- 'type' : 'CategoryExistence',
- 'portal_type' : ('Person', 'Organisation'),
- 'causality' : None,
- 'condition' : 'python: object.getPortalType() == 'Foo',
- },
+class CategoryExistenceConstraint(Constraint):
"""
+ This constraint checks whether a category has been defined on this
+ object (without acquisition). This is only relevant for ZODB
+ Property Sheets (filesystem Property Sheets rely on
+ Products.ERP5Type.Constraint.CategoryExistence instead).
+ """
+ meta_type = 'ERP5 Category Existence Constraint'
+ portal_type = 'Category Existence Constraint'
+
+ # Declarative security
+ security = ClassSecurityInfo()
+ security.declareObjectProtected(Permissions.AccessContentsInformation)
_message_id_list = [ 'message_category_not_set',
'message_category_not_associated_with_portal_type' ]
@@ -55,17 +58,19 @@ class CategoryExistence(Constraint):
return len(obj.getCategoryMembershipList(base_category,
portal_type=portal_type))
+ security.declareProtected(Permissions.AccessContentsInformation,
+ 'checkConsistency')
def checkConsistency(self, obj, fixit=0):
- """Check the object's consistency.
"""
- if not self._checkConstraintCondition(obj):
- return []
+ Check the object's consistency.
+ """
error_list = []
- portal_type = self.constraint_definition.get('portal_type', ())
+ if not self.test(obj):
+ return []
+
+ portal_type = self.getConstraintPortalTypeList() or ()
# For each attribute name, we check if defined
- for base_category in self.constraint_definition.keys():
- if base_category in ('portal_type', ):
- continue
+ for base_category in self.getConstraintBaseCategoryList() or ():
mapping = dict(base_category=base_category)
# Check existence of base category
if base_category not in obj.getBaseCategoryList():
@@ -74,29 +79,21 @@ class CategoryExistence(Constraint):
error_message = 'message_category_not_set'
else:
error_message = None
-
+
# Raise error
if error_message:
- error_list.append(self._generateError(obj,
- self._getMessage(error_message), mapping))
+ error_list.append(
+ self._generateError(obj,
+ self._getMessage(error_message), mapping))
return error_list
-
-class CategoryAcquiredExistence(CategoryExistence):
- """This constraint checks if an object respects the existence of a category,
- with acquisition.
-
- Configuration example:
- { 'id' : 'category_existence',
- 'description' : 'Category causality must be defined',
- 'type' : 'CategoryExistence',
- 'portal_type' : ('Person', 'Organisation'),
- 'causality' : None,
- 'condition' : 'python: object.getPortalType() == 'Foo',
- },
+class CategoryAcquiredExistenceConstraint(CategoryExistenceConstraint):
+ """
+ This constraint checks whether a category has been defined on this
+ object (with acquisition). This is only relevant for ZODB Property
+ Sheets (filesystem Property Sheets rely on
+ Products.ERP5Type.Constraint.CategoryExistence instead).
"""
-
def _calculateArity(self, obj, base_category, portal_type):
return len(obj.getAcquiredCategoryMembershipList(base_category,
portal_type=portal_type))
-
Copied: erp5/trunk/products/ERP5Type/Core/Constraint.py (from r39011, erp5/trunk/products/ERP5Type/Constraint/Constraint.py)
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Core/Constraint.py?p2=erp5/trunk/products/ERP5Type/Core/Constraint.py&p1=erp5/trunk/products/ERP5Type/Constraint/Constraint.py&r1=39011&r2=39348&rev=39348&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/Constraint/Constraint.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/Core/Constraint.py [utf8] Tue Oct 19 16:36:04 2010
@@ -1,9 +1,10 @@
##############################################################################
#
-# Copyright (c) 2002, 2005 Nexedi SARL and Contributors. All Rights Reserved.
-# Sebastien Robin <seb at nexedi.com>
-# Jean-Paul Smets <jp at nexedi.com>
-# Courteaud Romain <romain at nexedi.com>
+# Copyright (c) 2002-2010 Nexedi SARL and Contributors. All Rights Reserved.
+# Sebastien Robin <seb at nexedi.com>
+# Jean-Paul Smets <jp at nexedi.com>
+# Courteaud Romain <romain at nexedi.com>
+# Arnaud Fontaine <arnaud.fontaine at nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
@@ -28,91 +29,62 @@
#
##############################################################################
-from Products.CMFCore.Expression import Expression
from Products.ERP5Type.interfaces import IConstraint
from Products.ERP5Type.ConsistencyMessage import ConsistencyMessage
from zope.interface import implements
+from Products.ERP5Type.Core.Predicate import Predicate
+from AccessControl import ClassSecurityInfo
+from Products.ERP5Type import Permissions
+from Products.ERP5Type.Utils import UpperCase
+
+class Constraint(Predicate):
+ """
+ Constraint implementation (only relevant for ZODB Property sheets,
+ use Products.ERP5Type.Constraint instead for filesystem Property
+ Sheets) relying on Predicate
+ """
+ meta_type = 'ERP5 Constraint'
+ portal_type = 'Constraint'
+
+ # Declarative security
+ security = ClassSecurityInfo()
+ security.declareObjectProtected(Permissions.AccessContentsInformation)
-class Constraint:
+ __allow_access_to_unprotected_subobjects__ = 1
+ implements( IConstraint, )
+
+ _message_id_list = []
+
+ def _getMessage(self, message_id):
"""
- Default Constraint implementation
+ Get the message corresponding to this message_id.
"""
- __allow_access_to_unprotected_subobjects__ = 1
- implements( IConstraint, )
-
- _message_id_list = []
+ return getattr(self, 'get' + UpperCase(message_id))()
- def __init__(self, id=None, description=None, type=None,
- condition=None, **constraint_definition):
- """Initialize a constraint.
- """
- self.id = id
- self.description = description
- self.type = type
- self.constraint_definition = dict()
- self.message_id_dict = dict()
- self.edit(id, description, type, condition, **constraint_definition)
-
- def edit(self, id=None, description=None, type=None, condition=None,
- **constraint_definition):
- """Edit the constraint instance.
- """
- if id is not None:
- self.id = id
- if description is not None:
- self.description = description
- if type is not None:
- self.type = type
- self.condition = condition
- for key, value in constraint_definition.items():
- if key in self._message_id_list:
- self.message_id_dict[key] = value
- else:
- self.constraint_definition[key] = value
-
- def _getMessage(self, message_id):
- """Get the message corresponding to this message_id.
- """
- if message_id in self.message_id_dict:
- return self.message_id_dict[message_id]
- return getattr(self, message_id)
-
- def _generateError(self, obj, error_message, mapping={}):
- """Generic method used to generate error in checkConsistency.
- """
- if error_message is not None:
- msg = ConsistencyMessage(self,
- object_relative_url=obj.getRelativeUrl(),
- message=error_message,
- mapping=mapping)
- return msg
-
- def _checkConstraintCondition(self, obj):
- """
- method that will check if the TALES condition is true.
- It should be called by checkConsistency, which should ignore
- constraints if TALES is False
- """
- from Products.ERP5Type.Utils import createExpressionContext
- condition = getattr(self, 'condition', None)
- if condition not in (None, ''):
- expression = Expression(condition)
- econtext = createExpressionContext(obj)
- if not expression(econtext):
- return 0 # a condition was defined and is False
- return 1 # no condition or a True condition was defined
-
- def checkConsistency(self, obj, fixit=0, **kw):
- """
- Default method is to return no error.
- """
- errors = []
- return errors
-
- def fixConsistency(self, obj, **kw):
- """
- Default method is to call checkConsistency with
- fixit set to 1
- """
- return self.checkConsistency(obj, fixit=1, **kw)
+ def _generateError(self, obj, error_message, mapping={}):
+ """
+ Generic method used to generate error in checkConsistency.
+ """
+ if error_message is not None:
+ msg = ConsistencyMessage(self,
+ object_relative_url=obj.getRelativeUrl(),
+ message=error_message,
+ mapping=mapping)
+ return msg
+
+ security.declareProtected(Permissions.AccessContentsInformation,
+ 'checkConsistency')
+ def checkConsistency(self, obj, fixit=0, **kw):
+ """
+ Default method is to return no error.
+ """
+ errors = []
+ return errors
+ security.declareProtected(Permissions.AccessContentsInformation,
+ 'fixConsistency')
+ def fixConsistency(self, obj, **kw):
+ """
+ Default method is to call checkConsistency with fixit set to 1
+ """
+ return self.checkConsistency(obj, fixit=1, **kw)
Copied: erp5/trunk/products/ERP5Type/Core/PropertyExistenceConstraint.py (from r39011, erp5/trunk/products/ERP5Type/Constraint/PropertyExistence.py)
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Core/PropertyExistenceConstraint.py?p2=erp5/trunk/products/ERP5Type/Core/PropertyExistenceConstraint.py&p1=erp5/trunk/products/ERP5Type/Constraint/PropertyExistence.py&r1=39011&r2=39348&rev=39348&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/Constraint/PropertyExistence.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/Core/PropertyExistenceConstraint.py [utf8] Tue Oct 19 16:36:04 2010
@@ -1,8 +1,9 @@
##############################################################################
#
-# Copyright (c) 2002, 2005 Nexedi SARL and Contributors. All Rights Reserved.
-# Sebastien Robin <seb at nexedi.com>
-# Romain Courteaud <romain at nexedi.com>
+# Copyright (c) 2002-2010 Nexedi SARL and Contributors. All Rights Reserved.
+# Sebastien Robin <seb at nexedi.com>
+# Romain Courteaud <romain at nexedi.com>
+# Arnaud Fontaine <arnaud.fontaine at nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
@@ -27,23 +28,31 @@
#
##############################################################################
-from Constraint import Constraint
+from Products.ERP5Type.Core.Constraint import Constraint
+from AccessControl import ClassSecurityInfo
+from Products.ERP5Type import Permissions
-class PropertyExistence(Constraint):
+class PropertyExistenceConstraint(Constraint):
"""
- This method checks if an object respects the existence of a property.
-
- For example we can check if every invoice line has a price defined
- on it.
- Configuration example:
- { 'id' : 'property_existence',
- 'description' : 'Property price must be defined',
- 'type' : 'PropertyExistence',
- 'price' : None,
- 'condition' : 'python: object.getPortalType() == 'Foo',
- },
+ This constraint checks whether a property has been defined on this
+ object. This is only relevant for ZODB Property Sheets (filesystem
+ Property Sheets rely on Products.ERP5Type.Constraint.PropertyExistence
+ instead).
+
+ For example, if we would like to check whether an invoice line has a
+ 'price' property defined on it, we would create a 'Property
+ Existence Constraint' within that property sheet and add 'price' to
+ the 'Properties' field, then set the 'Predicate' if necessary (known
+ as 'condition' for filesystem Property Sheets).
"""
+ meta_type = 'ERP5 Property Existence Constraint'
+ portal_type = 'Property Existence Constraint'
+
+ # Declarative security
+ security = ClassSecurityInfo()
+ security.declareObjectProtected(Permissions.AccessContentsInformation)
+ # Define by default error messages
_message_id_list = ['message_no_such_property',
'message_property_not_set']
message_no_such_property = "Property existence error for property "\
@@ -51,14 +60,18 @@ class PropertyExistence(Constraint):
message_property_not_set = "Property existence error for property "\
"${property_id}, this property is not defined"
+ security.declareProtected(Permissions.AccessContentsInformation,
+ 'checkConsistency')
def checkConsistency(self, obj, fixit=0):
- """Check the object's consistency.
"""
- if not self._checkConstraintCondition(obj):
- return []
+ Check the object's consistency.
+ """
error_list = []
+ if not self.test(obj):
+ return []
+
# For each attribute name, we check if defined
- for property_id in self.constraint_definition.keys():
+ for property_id in self.getConstraintPropertyList() or ():
# Check existence of property
mapping = dict(property_id=property_id)
if not obj.hasProperty(property_id):
Modified: erp5/trunk/products/ERP5Type/Dynamic/portaltypeclass.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Dynamic/portaltypeclass.py?rev=39348&r1=39347&r2=39348&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/Dynamic/portaltypeclass.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/Dynamic/portaltypeclass.py [utf8] Tue Oct 19 16:36:04 2010
@@ -38,8 +38,9 @@ import lazyclass
from Products.ERP5Type.Globals import InitializeClass
from Products.ERP5Type.Utils import setDefaultClassProperties
from Products.ERP5Type import document_class_registry, mixin_class_registry
+from Products.ERP5Type import PropertySheet as FilesystemPropertySheet
from ExtensionClass import Base as ExtensionBase
-from zLOG import LOG, ERROR, BLATHER
+from zLOG import LOG, ERROR, INFO
def _import_class(classpath):
try:
@@ -57,22 +58,49 @@ def _import_class(classpath):
raise ImportError('Could not import document class %s' % classpath)
def _create_accessor_holder_class(property_sheet_tool,
+ property_sheet_module,
property_sheet_name):
"""
If the given Property Sheet exists in portal_property_sheets, then
generate its accessor holder
"""
- try:
- return property_sheet_tool.createPropertySheetAccessorHolder(
- getattr(property_sheet_tool,
- property_sheet_name))
-
- except AttributeError:
- # Not too critical
- LOG("ERP5Type.Dynamic", ERROR,
- "Ignoring missing Property Sheet " + property_sheet_name)
- return None
+def _fill_accessor_holder_list(accessor_holder_list,
+ create_accessor_holder_func,
+ property_sheet_name_set,
+ accessor_holder_module,
+ property_sheet_module):
+ """
+ Fill the accessor holder list with the given Property Sheets (which
+ could be coming either from the filesystem or ZODB)
+ """
+ for property_sheet_name in property_sheet_name_set:
+ try:
+ # Get the already generated accessor holder
+ accessor_holder_list.append(getattr(accessor_holder_module,
+ property_sheet_name))
+
+ except AttributeError:
+ # Generate the accessor holder as it has not been done yet
+ try:
+ accessor_holder_class = \
+ create_accessor_holder_func(getattr(property_sheet_module,
+ property_sheet_name))
+
+ except AttributeError:
+ # Not too critical
+ LOG("ERP5Type.Dynamic", ERROR,
+ "Ignoring missing Property Sheet " + property_sheet_name)
+
+ else:
+ setattr(accessor_holder_module, property_sheet_name,
+ accessor_holder_class)
+
+ accessor_holder_list.append(accessor_holder_class)
+
+ LOG("ERP5Type.Dynamic", INFO,
+ "Created accessor holder for %s in %s" % (property_sheet_name,
+ accessor_holder_module))
def portal_type_factory(portal_type_name):
"""
@@ -134,33 +162,27 @@ def portal_type_factory(portal_type_name
"Could not load interfaces or Mixins for portal type %s" \
% portal_type)
- # Initialize Property Sheets accessor holders
- import erp5.accessor_holder
-
- # Get the ZODB Property Sheets for this Portal Type
- property_sheet_name_set = set(
- portal_type.getNewStyleTypePropertySheetList() or [])
-
- for property_sheet_name in property_sheet_name_set:
- try:
- # Get the already generated accessor holder
- accessor_holder_list.append(getattr(erp5.accessor_holder,
- property_sheet_name))
-
- except AttributeError:
- # Generate the accessor holder as it has not been done yet
- accessor_holder_class = \
- _create_accessor_holder_class(site.portal_property_sheets,
- property_sheet_name)
-
- if accessor_holder_class is not None:
- setattr(erp5.accessor_holder, property_sheet_name,
- accessor_holder_class)
-
- accessor_holder_list.append(accessor_holder_class)
+ import erp5
- LOG("ERP5Type.Dynamic", BLATHER,
- "Created accessor holder for %s" % property_sheet_name)
+ # Initialize filesystem Property Sheets accessor holders
+ _fill_accessor_holder_list(
+ accessor_holder_list,
+ site.portal_property_sheets.createFilesystemPropertySheetAccessorHolder,
+ set(portal_type.getTypePropertySheetList() or ()),
+ erp5.filesystem_accessor_holder,
+ FilesystemPropertySheet)
+
+ # Initialize ZODB Property Sheets accessor holders
+ _fill_accessor_holder_list(
+ accessor_holder_list,
+ site.portal_property_sheets.createZodbPropertySheetAccessorHolder,
+ set(portal_type.getTypeZodbPropertySheetList() or ()),
+ erp5.zodb_accessor_holder,
+ site.portal_property_sheets)
+
+ LOG("ERP5Type.Dynamic", INFO,
+ "%s: accessor_holder_list: %s" % (portal_type_name,
+ accessor_holder_list))
if type_class is not None:
type_class = document_class_registry.get(type_class)
@@ -176,7 +198,7 @@ def portal_type_factory(portal_type_name
baseclasses = [type_class] + accessor_holder_list + mixin_class_list
- LOG("ERP5Type.Dynamic", BLATHER,
+ LOG("ERP5Type.Dynamic", INFO,
"Portal type %s loaded with bases %s" \
% (portal_type_name, repr(baseclasses)))
@@ -193,8 +215,13 @@ def initializeDynamicModules():
holds document classes that have no physical import path,
for example classes created through ClassTool that are in
$INSTANCE_HOME/Document
- erp5.accessor_holder
- holds accessors of ZODB Property Sheet
+ erp5.zodb_accessor_holder
+ holds accessors of ZODB Property Sheets
+ erp5.filesystem_accessor_holder
+ holds accessors of filesystem Property Sheets
+
+ XXX: there should be only one accessor_holder once the code is
+ stable and all the Property Sheets have been migrated
"""
def portal_type_loader(portal_type_name):
"""
@@ -206,8 +233,11 @@ def initializeDynamicModules():
sys.modules["erp5"] = erp5
erp5.document = ModuleType("erp5.document")
sys.modules["erp5.document"] = erp5.document
- erp5.accessor_holder = ModuleType("erp5.accessor_holder")
- sys.modules["erp5.accessor_holder"] = erp5.accessor_holder
+
+ erp5.zodb_accessor_holder = ModuleType("erp5.zodb_accessor_holder")
+ sys.modules["erp5.zodb_accessor_holder"] = erp5.zodb_accessor_holder
+ erp5.filesystem_accessor_holder = ModuleType("erp5.filesystem_accessor_holder")
+ sys.modules["erp5.filesystem_accessor_holder"] = erp5.filesystem_accessor_holder
portal_type_container = dynamicmodule.dynamicmodule('erp5.portal_type',
portal_type_loader)
@@ -249,6 +279,18 @@ def initializeDynamicModules():
erp5.temp_portal_type = dynamicmodule.dynamicmodule('erp5.temp_portal_type',
temp_portal_type_loader)
+def _clear_accessor_holder_module(module):
+ """
+ Clear the given accessor holder module (either for filesystem or
+ ZODB)
+
+ XXX: Merge into synchronizeDynamicModules as soon as we get rid of
+ these two accessor holder modules
+ """
+ for property_sheet_id in module.__dict__.keys():
+ if not property_sheet_id.startswith('__'):
+ delattr(module, property_sheet_id)
+
last_sync = 0
def synchronizeDynamicModules(context, force=False):
"""
@@ -262,7 +304,7 @@ def synchronizeDynamicModules(context, f
and send out an invalidation to other nodes
"""
return # XXX disabled for now
- LOG("ERP5Type.Dynamic", BLATHER, "Resetting dynamic classes")
+ LOG("ERP5Type.Dynamic", INFO, "Resetting dynamic classes")
portal = context.getPortalObject()
@@ -291,6 +333,7 @@ def synchronizeDynamicModules(context, f
type(ExtensionBase).__init__(klass, klass)
# Clear accessor holders of ZODB Property Sheets
- for accessor_name in erp5.accessor_holder.__dict__.keys():
- if not accessor_name.startswith('__'):
- delattr(erp5.accessor_holder, accessor_name)
+ _clear_accessor_holder_module(erp5.zodb_accessor_holder)
+
+ # Clear accessor holders of filesystem Property Sheets
+ _clear_accessor_holder_module(erp5.filesystem_accessor_holder)
Modified: erp5/trunk/products/ERP5Type/Tool/PropertySheetTool.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Tool/PropertySheetTool.py?rev=39348&r1=39347&r2=39348&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/Tool/PropertySheetTool.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/Tool/PropertySheetTool.py [utf8] Tue Oct 19 16:36:04 2010
@@ -38,12 +38,6 @@ from Products.ERP5Type.Utils import setD
from zLOG import LOG, ERROR, BLATHER
-class AccessorHolder(object):
- """
- Base class of an accessor holder class for Property Sheets
- """
- pass
-
class PropertySheetTool(BaseTool):
"""
Provides a configurable registry of property sheets
@@ -87,8 +81,6 @@ class PropertySheetTool(BaseTool):
"""
Create a new Property Sheet in portal_property_sheets from a given
filesystem-based Property Sheet definition.
-
- XXX: Implement constraints
"""
new_property_sheet = self.newContent(id=klass.__name__,
portal_type='Property Sheet')
@@ -151,7 +143,8 @@ class PropertySheetTool(BaseTool):
Export a given ZODB Property Sheet to its filesystem definition as
tuple (properties, categories, constraints)
- XXX: Implement constraints
+ XXX: Move this code and the accessor generation code (from Utils)
+ within their respective documents
"""
properties = []
constraints = []
@@ -170,26 +163,21 @@ class PropertySheetTool(BaseTool):
elif portal_type == "Dynamic Category Property":
categories.append(property.exportToFilesystemDefinition())
- return (properties, categories, constraints, )
-
- security.declarePrivate('createPropertySheetAccessorHolder')
- def createPropertySheetAccessorHolder(self, property_sheet):
+ elif portal_type.endswith('Constraint'):
+ from Acquisition import aq_base
+ constraints.append(aq_base(property.asContext()))
+
+ return (properties, categories, constraints)
+
+ def _createCommonPropertySheetAccessorHolder(self,
+ property_holder,
+ property_sheet_id,
+ accessor_holder_module_name):
+ """
+ Create a new accessor holder class from the given Property Holder
+ within the given accessor holder module (when the migration will
+ be finished, there should only be one accessor holder module)
"""
- Create a new accessor holder from the given Property Sheet (the
- accessors are created through a Property Holder)
-
- XXX: Workflows?
- """
- property_holder = PropertyHolder()
-
- definition_tuple = \
- self.exportPropertySheetToFilesystemDefinitionTuple(property_sheet)
-
- # Prepare the Property Holder
- property_holder._properties, \
- property_holder._categories, \
- property_holder._constraints = definition_tuple
-
setDefaultClassProperties(property_holder)
try:
@@ -197,16 +185,26 @@ class PropertySheetTool(BaseTool):
except:
import traceback
LOG("Tool.PropertySheetTool", ERROR,
- "Could not generate accessor holder class for %s: %s" % \
- (property_sheet.getTitle(), traceback.format_exc()))
+ "Could not generate accessor holder class for %s (module=%s): %s" %\
+ (property_sheet_id,
+ accessor_holder_module_name,
+ traceback.format_exc()))
return None
# Create the new accessor holder class and set its module properly
- accessor_holder_class = type(property_sheet.getId(),
- (AccessorHolder,), {})
-
- accessor_holder_class.__module__ = 'erp5.accessor_holder'
+ accessor_holder_class = type(property_sheet_id, (object,), dict(
+ __module__ = accessor_holder_module_name,
+ constraints = property_holder.constraints,
+ # The following attributes have been defined only because they
+ # are being used in ERP5Type.Utils when getting all the
+ # property_sheets of the property_holder (then, they are added
+ # to the local properties, categories and constraints lists)
+ _properties = property_holder._properties,
+ # Necessary for getBaseCategoryList
+ _categories = property_holder._categories,
+ _constraints = property_holder._constraints
+ ))
# Set all the accessors (defined by a tuple) from the Property
# Holder to the new accessor holder class (code coming from
@@ -227,3 +225,46 @@ class PropertySheetTool(BaseTool):
setattr(accessor_holder_class, id, accessor)
return accessor_holder_class
+
+ security.declarePrivate('createFilesystemPropertySheetAccessorHolder')
+ def createFilesystemPropertySheetAccessorHolder(self, property_sheet):
+ """
+ Create a new accessor holder from the given filesystem Property
+ Sheet (the accessors are created through a Property Holder)
+
+ XXX: Workflows?
+ XXX: Remove as soon as the migration is finished
+ """
+ property_holder = PropertyHolder()
+
+ property_holder._properties = getattr(property_sheet, '_properties', [])
+ property_holder._categories = getattr(property_sheet, '_categories', [])
+ property_holder._constraints = getattr(property_sheet, '_constraints', [])
+
+ return self._createCommonPropertySheetAccessorHolder(
+ property_holder,
+ property_sheet.__name__,
+ 'erp5.filesystem_accessor_holder')
+
+ security.declarePrivate('createZodbPropertySheetAccessorHolder')
+ def createZodbPropertySheetAccessorHolder(self, property_sheet):
+ """
+ Create a new accessor holder from the given ZODB Property Sheet
+ (the accessors are created through a Property Holder)
+
+ XXX: Workflows?
+ """
+ definition_tuple = \
+ self.exportPropertySheetToFilesystemDefinitionTuple(property_sheet)
+
+ property_holder = PropertyHolder()
+
+ # Prepare the Property Holder
+ property_holder._properties, \
+ property_holder._categories, \
+ property_holder._constraints = definition_tuple
+
+ return self._createCommonPropertySheetAccessorHolder(
+ property_holder,
+ property_sheet.getId(),
+ 'erp5.zodb_accessor_holder')
More information about the Erp5-report
mailing list