Commit 13c22d1a authored by Arnaud Fontaine's avatar Arnaud Fontaine

Accessors generation is now performed in StandardProperty, AcquiredProperty,

CategoryProperty and DynamicCategoryProperty rather than setDefaultProperties
from Utils.

erp5.accessor_holder has also been split up into two additional modules, namely 
erp5.accessor_holder.property_sheet, containing accessor holders for ZODB 
Property Sheets, and erp5.accessor_holder.portal_type, containing accessor 
holders specific to the Portal Types (only being used by PreferenceTool and egov 
for now). erp5.accessor_holder only contains accessor holders common to both 
Portal Types and Property Sheets (such as BaseAccessorHolder).

This commit also enables code committed in r43886.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@43892 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent f38a05c2
...@@ -325,92 +325,21 @@ class PropertyHolder(object): ...@@ -325,92 +325,21 @@ class PropertyHolder(object):
return [x for x in self.__dict__.items() if x[0] not in return [x for x in self.__dict__.items() if x[0] not in
PropertyHolder.RESERVED_PROPERTY_SET] PropertyHolder.RESERVED_PROPERTY_SET]
# Accessor generation def registerWorkflowMethod(self, id, wf_id, tr_id, once_per_transaction=0):
def createAccessor(self, id): portal_type = self.portal_type
"""
Invokes appropriate factory and create an accessor
"""
fake_accessor = getattr(self, id)
ptype = getattr(self, 'portal_type', None)
if ptype is None:
ptype = self._portal_type
if fake_accessor is PropertyHolder.WORKFLOW_METHOD_MARKER:
# Case 1 : a workflow method only
accessor = Base._doNothing
else:
# Case 2 : a workflow method over an accessor
(accessor_class, accessor_args, key) = fake_accessor
accessor = accessor_class(id, key, *accessor_args)
for wf_id, tr_id, once in self.workflow_method_registry.get(id, ()):
if not isinstance(accessor, WorkflowMethod):
accessor = WorkflowMethod(accessor)
if once:
accessor.registerTransitionOncePerTransaction(ptype, wf_id, tr_id)
else:
accessor.registerTransitionAlways(ptype, wf_id, tr_id)
else:
if once:
accessor.registerTransitionOncePerTransaction(ptype, wf_id, tr_id)
else:
accessor.registerTransitionAlways(ptype, wf_id, tr_id)
setattr(self, id, accessor)
return accessor
def registerAccessor(self, id, key, accessor_class, accessor_args):
"""
Saves in a dictionary all parameters required to create an accessor
The goal here is to minimize memory occupation. We have found the following:
- the size of a tuple with simple types and the size
of None are the same (a pointer)
- the size of a pointer to a class is the same as the
size of None
- the python caching system for tuples is efficient for tuples
which contain simple types (string, int, etc.) but innefficient
for tuples which contain a pointer
- as a result, it is better to create separate dicts if
values contain pointers and single dict if value is
a tuple of simple types
Parameters:
id -- The id the accessor (ex. getFirstName)
key -- The id of the property (ex. first_name) or the id of the workflow_method = getattr(self, id, None)
method for Alias accessors if workflow_method is None:
""" workflow_method = WorkflowMethod(Base._doNothing)
#LOG('registerAccessor', 0, "%s %s %s" % (id , self._portal_type, accessor_args)) setattr(self, id, workflow_method)
# First we try to compress the information required if once_per_transaction:
# to build a new accessor in such way that workflow_method.registerTransitionOncePerTransaction(portal_type,
# if the same information is provided twice, we wf_id,
# shall keep it once only tr_id)
new_accessor_args = []
for arg in accessor_args:
if type(arg) is types.ListType:
new_accessor_args.append(tuple(arg))
else: else:
new_accessor_args.append(arg) workflow_method.registerTransitionAlways(portal_type,
accessor_args = tuple(new_accessor_args) wf_id,
original_registration_tuple = (accessor_class, accessor_args, key) tr_id)
registration_tuple = method_registration_cache.get(original_registration_tuple)
if registration_tuple is None:
registration_tuple = original_registration_tuple
method_registration_cache[registration_tuple] = registration_tuple
# Use the cached tuple (same value, different pointer)
setattr(self, id, registration_tuple)
def registerWorkflowMethod(self, id, wf_id, tr_id, once_per_transaction=0):
#LOG('registerWorkflowMethod', 0, "%s %s %s %s %s" % (self._portal_type, id, wf_id, tr_id, once_per_transaction))
signature = (wf_id, tr_id, once_per_transaction)
signature_list = self.workflow_method_registry.get(id, ())
if signature not in signature_list:
self.workflow_method_registry[id] = signature_list + (signature,)
if getattr(self, id, None) is None:
setattr(self, id, PropertyHolder.WORKFLOW_METHOD_MARKER)
self.createAccessor(id)
def declareProtected(self, permission, accessor_name): def declareProtected(self, permission, accessor_name):
""" """
...@@ -520,23 +449,6 @@ def getClassPropertyList(klass): ...@@ -520,23 +449,6 @@ def getClassPropertyList(klass):
if p not in ps_list]) if p not in ps_list])
return ps_list return ps_list
def initializeClassDynamicProperties(self, klass):
if klass not in Base.aq_method_generated:
# Recurse to superclasses
for super_klass in klass.__bases__:
if getattr(super_klass, 'isRADContent', 0):
initializeClassDynamicProperties(self, super_klass)
# Initialize default properties
from Utils import setDefaultClassProperties
if not getattr(klass, 'isPortalContent', None):
if getattr(klass, 'isRADContent', 0):
setDefaultClassProperties(klass)
# Mark as generated
Base.aq_method_generated.add(klass)
def initializePortalTypeDynamicProperties(self, klass, ptype, aq_key, portal):
raise ValueError("No reason to go through this no more with portal type classes")
def initializePortalTypeDynamicWorkflowMethods(ptype_klass, portal_workflow): def initializePortalTypeDynamicWorkflowMethods(ptype_klass, portal_workflow):
"""We should now make sure workflow methods are defined """We should now make sure workflow methods are defined
and also make sure simulation state is defined.""" and also make sure simulation state is defined."""
...@@ -567,10 +479,8 @@ def initializePortalTypeDynamicWorkflowMethods(ptype_klass, portal_workflow): ...@@ -567,10 +479,8 @@ def initializePortalTypeDynamicWorkflowMethods(ptype_klass, portal_workflow):
if not hasattr(ptype_klass, method_id): if not hasattr(ptype_klass, method_id):
method = getter(method_id, wf_id) method = getter(method_id, wf_id)
# Attach to portal_type # Attach to portal_type
setattr(ptype_klass, method_id, method) ptype_klass.registerAccessor(method,
ptype_klass.security.declareProtected( Permissions.AccessContentsInformation)
Permissions.AccessContentsInformation,
method_id )
storage = dc_workflow_dict storage = dc_workflow_dict
transitions = wf.transitions transitions = wf.transitions
...@@ -806,12 +716,6 @@ class Base( CopyContainer, ...@@ -806,12 +716,6 @@ class Base( CopyContainer,
self._setDescription(value) self._setDescription(value)
self.reindexObject() self.reindexObject()
security.declareProtected( Permissions.AccessContentsInformation, 'test_dyn' )
def test_dyn(self):
"""
"""
initializeClassDynamicProperties(self, self.__class__)
security.declarePublic('provides') security.declarePublic('provides')
def provides(cls, interface_name): def provides(cls, interface_name):
""" """
...@@ -848,18 +752,6 @@ class Base( CopyContainer, ...@@ -848,18 +752,6 @@ class Base( CopyContainer,
pformat(rev1.__dict__), pformat(rev1.__dict__),
pformat(rev2.__dict__))) pformat(rev2.__dict__)))
def initializePortalTypeDynamicProperties(self):
"""
Test purpose
"""
ptype = self.portal_type
klass = self.__class__
aq_key = self._aq_key()
initializePortalTypeDynamicProperties(self, klass, ptype, aq_key, \
self.getPortalObject())
from Products.ERP5Form.PreferenceTool import createPreferenceToolAccessorList
createPreferenceToolAccessorList(self.getPortalObject())
def _aq_dynamic(self, id): def _aq_dynamic(self, id):
# ahah! disabled, thanks to portal type classes # ahah! disabled, thanks to portal type classes
return None return None
......
...@@ -48,6 +48,7 @@ class PropertySheet(Folder): ...@@ -48,6 +48,7 @@ class PropertySheet(Folder):
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
# TODO: REMOVE
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'exportToFilesystemDefinition') 'exportToFilesystemDefinition')
def exportToFilesystemDefinition(self): def exportToFilesystemDefinition(self):
...@@ -86,22 +87,15 @@ class PropertySheet(Folder): ...@@ -86,22 +87,15 @@ class PropertySheet(Folder):
return (properties, categories, constraints) return (properties, categories, constraints)
security.declarePrivate('createAccessorHolder') security.declarePrivate('createAccessorHolder')
def createAccessorHolder(self): def createAccessorHolder(self, expression_context, portal):
""" """
Create a new accessor holder from the Property Sheet (the Create a new accessor holder from the Property Sheet
accessors are created through a Property Holder)
""" """
property_holder = PropertyHolder(self.getId()) accessor_holder = AccessorHolderType(self.getId())
# Prepare the Property Holder self.applyOnAccessorHolder(accessor_holder, expression_context, portal)
property_holder._properties, \
property_holder._categories, \
property_holder._constraints = self.exportToFilesystemDefinition()
return AccessorHolderType.fromPropertyHolder( return accessor_holder
property_holder,
self.getPortalObject(),
'erp5.accessor_holder')
@staticmethod @staticmethod
def _guessFilesystemPropertyPortalType(attribute_dict): def _guessFilesystemPropertyPortalType(attribute_dict):
......
This diff is collapsed.
...@@ -7,8 +7,8 @@ from Products.ERP5Type.Accessor.Constant import Getter as ConstantGetter ...@@ -7,8 +7,8 @@ from Products.ERP5Type.Accessor.Constant import Getter as ConstantGetter
from Products.ERP5Type.Globals import InitializeClass from Products.ERP5Type.Globals import InitializeClass
from Products.ERP5Type.Base import Base as ERP5Base from Products.ERP5Type.Base import Base as ERP5Base
from Products.ERP5Type.Base import PropertyHolder, initializePortalTypeDynamicWorkflowMethods from Products.ERP5Type.Base import PropertyHolder, initializePortalTypeDynamicWorkflowMethods
from Products.ERP5Type.Utils import createAllCategoryAccessors, \ from Products.ERP5Type.Utils import UpperCase
createExpressionContext, UpperCase, setDefaultProperties from Products.ERP5Type.Core.CategoryProperty import CategoryProperty
from ExtensionClass import ExtensionClass, pmc_init_of from ExtensionClass import ExtensionClass, pmc_init_of
from zope.interface import classImplements from zope.interface import classImplements
...@@ -130,11 +130,11 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder): ...@@ -130,11 +130,11 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder):
cls.security = ClassSecurityInfo() cls.security = ClassSecurityInfo()
@classmethod @classmethod
def getSubclassList(metacls, cls): def getSubclassList(meta_class, cls):
""" """
Returns classes deriving from cls Returns classes deriving from cls
""" """
return metacls.subclass_register.get(cls, []) return meta_class.subclass_register.get(cls, [])
def getAccessorHolderPropertyList(cls): def getAccessorHolderPropertyList(cls):
""" """
...@@ -145,10 +145,12 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder): ...@@ -145,10 +145,12 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder):
""" """
cls.loadClass() cls.loadClass()
property_dict = {} property_dict = {}
for klass in cls.mro(): for klass in cls.mro():
if klass.__module__ == 'erp5.accessor_holder': if klass.__module__.startswith('erp5.accessor_holder'):
for property in klass._properties: for property in klass._properties:
property_dict.setdefault(property['id'], property) property_dict.setdefault(property['id'], property)
return property_dict.values() return property_dict.values()
def resetAcquisition(cls): def resetAcquisition(cls):
...@@ -210,36 +212,12 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder): ...@@ -210,36 +212,12 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder):
raise AttributeError raise AttributeError
def generatePortalTypeAccessors(cls, site, portal_type_category_list): def generatePortalTypeAccessors(cls, site, portal_type_category_list):
createAllCategoryAccessors(site, category_tool = getattr(site, 'portal_categories', None)
cls, for category_id in portal_type_category_list:
portal_type_category_list, # we need to generate only categories defined on portal type
createExpressionContext(site, site)) CategoryProperty.applyDefinitionOnAccessorHolder(cls,
category_id,
# Properties defined on the portal type itself are generated in category_tool)
# erp5.portal_type directly, but this is unusual case (only
# PDFTypeInformation seems to use it)
portal_type_property_list = getattr(cls, '_properties', None)
if portal_type_property_list:
setDefaultProperties(cls)
# make sure that category accessors from the portal type definition
# are generated, no matter what
# XXX this code is duplicated here, in PropertySheetTool, and in Base
# and anyway is ugly, as tuple-like registration does not help
for id, fake_accessor in cls._getPropertyHolderItemList():
if not isinstance(fake_accessor, tuple):
continue
if fake_accessor is PropertyHolder.WORKFLOW_METHOD_MARKER:
# Case 1 : a workflow method only
accessor = ERP5Base._doNothing
else:
# Case 2 : a workflow method over an accessor
(accessor_class, accessor_args, key) = fake_accessor
accessor = accessor_class(id, key, *accessor_args)
# Add the accessor to the accessor holder
setattr(cls, id, accessor)
portal_workflow = getattr(site, 'portal_workflow', None) portal_workflow = getattr(site, 'portal_workflow', None)
if portal_workflow is None: if portal_workflow is None:
...@@ -259,9 +237,8 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder): ...@@ -259,9 +237,8 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder):
for group in ERP5TypeInformation.defined_group_list: for group in ERP5TypeInformation.defined_group_list:
value = cls.__name__ in site._getPortalGroupedTypeSet(group) value = cls.__name__ in site._getPortalGroupedTypeSet(group)
accessor_name = 'is' + UpperCase(group) + 'Type' accessor_name = 'is' + UpperCase(group) + 'Type'
setattr(cls, accessor_name, ConstantGetter(accessor_name, group, value)) method = ConstantGetter(accessor_name, group, value)
cls.declareProtected(Permissions.AccessContentsInformation, cls.registerAccessor(method, Permissions.AccessContentsInformation)
accessor_name)
from Products.ERP5Type.Cache import initializePortalCachingProperties from Products.ERP5Type.Cache import initializePortalCachingProperties
initializePortalCachingProperties(site) initializePortalCachingProperties(site)
...@@ -274,7 +251,7 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder): ...@@ -274,7 +251,7 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder):
cls.loadClass() cls.loadClass()
result = PropertyHolder._getPropertyHolderItemList(cls) result = PropertyHolder._getPropertyHolderItemList(cls)
for parent in cls.mro(): for parent in cls.mro():
if parent.__module__ == 'erp5.accessor_holder': if parent.__module__.startswith('erp5.accessor_holder'):
for x in parent.__dict__.items(): for x in parent.__dict__.items():
if x[0] not in PropertyHolder.RESERVED_PROPERTY_SET: if x[0] not in PropertyHolder.RESERVED_PROPERTY_SET:
result.append(x) result.append(x)
......
...@@ -32,16 +32,14 @@ import os ...@@ -32,16 +32,14 @@ import os
import inspect import inspect
from types import ModuleType from types import ModuleType
from dynamic_module import registerDynamicModule from Products.ERP5Type.dynamic.dynamic_module import registerDynamicModule
from accessor_holder import _generateBaseAccessorHolder, \
_generatePreferenceToolAccessorHolder
from Products.ERP5Type.mixin.temporary import TemporaryDocumentMixin from Products.ERP5Type.mixin.temporary import TemporaryDocumentMixin
from Products.ERP5Type.Base import Base, resetRegisteredWorkflowMethod from Products.ERP5Type.Base import Base, resetRegisteredWorkflowMethod
from Products.ERP5Type.Globals import InitializeClass from Products.ERP5Type.Globals import InitializeClass
from Products.ERP5Type.Utils import setDefaultClassProperties from Products.ERP5Type.Utils import setDefaultClassProperties
from Products.ERP5Type import document_class_registry, mixin_class_registry from Products.ERP5Type import document_class_registry, mixin_class_registry
from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter from Products.ERP5Type.dynamic.accessor_holder import AccessorHolderModuleType, \
createAllAccessorHolderList
from zLOG import LOG, ERROR, INFO, WARNING from zLOG import LOG, ERROR, INFO, WARNING
...@@ -59,71 +57,6 @@ def _importClass(classpath): ...@@ -59,71 +57,6 @@ def _importClass(classpath):
except StandardError: except StandardError:
raise ImportError('Could not import document class %s' % classpath) raise ImportError('Could not import document class %s' % classpath)
def _createAccessorHolderList(site,
portal_type_name,
property_sheet_name_set):
"""
Create the accessor holder list with the given ZODB Property Sheets
"""
from erp5 import accessor_holder
getPropertySheet = site.portal_property_sheets._getOb
accessor_holder_list = []
if "Base" in property_sheet_name_set:
# useless if Base Category is not yet here or if we're currently
# generating accessors for Base Categories
accessor_holder_class = _generateBaseAccessorHolder(site, accessor_holder)
if accessor_holder_class is not None:
accessor_holder_list.append(accessor_holder_class)
for property_sheet_name in property_sheet_name_set:
# LOG("ERP5Type.dynamic", INFO,
# "Getting accessor holder for " + property_sheet_name)
try:
# Get the already generated accessor holder
accessor_holder_list.append(getattr(accessor_holder, property_sheet_name))
except AttributeError:
try:
property_sheet = getPropertySheet(property_sheet_name)
except KeyError:
LOG("ERP5Type.dynamic", WARNING,
"Ignoring missing Property Sheet " + property_sheet_name)
continue
# Generate the accessor holder as it has not been done yet
try:
accessor_holder_class = property_sheet.createAccessorHolder()
except Exception:
LOG("ERP5Type.dynamic", ERROR,
"Invalid Property Sheet " + property_sheet_name)
raise
accessor_holder_list.append(accessor_holder_class)
setattr(accessor_holder, property_sheet_name, accessor_holder_class)
# LOG("ERP5Type.dynamic", INFO,
# "Created accessor holder for %s" % property_sheet_name)
# XXX a hook to add per-portal type accessor holders maybe?
if portal_type_name == "Preference Tool":
accessor_holder_class = \
_generatePreferenceToolAccessorHolder(site,
accessor_holder_list,
accessor_holder)
accessor_holder_list.insert(0, accessor_holder_class)
# LOG("ERP5Type.dynamic", INFO,
# "Got accessor holder for %s: %s" % (property_sheet_name, accessor_holder_list))
return accessor_holder_list
# Loading Cache Factory portal type would generate the accessor holder # Loading Cache Factory portal type would generate the accessor holder
# for Cache Factory, itself defined with Standard Property thus # for Cache Factory, itself defined with Standard Property thus
# loading the portal type Standard Property, itself defined with # loading the portal type Standard Property, itself defined with
...@@ -177,7 +110,6 @@ def generatePortalTypeClass(site, portal_type_name): ...@@ -177,7 +110,6 @@ def generatePortalTypeClass(site, portal_type_name):
portal_type_category_list = [] portal_type_category_list = []
attribute_dict = dict(portal_type=portal_type_name, attribute_dict = dict(portal_type=portal_type_name,
_properties=[],
_categories=[], _categories=[],
constraints=[]) constraints=[])
...@@ -269,73 +201,11 @@ def generatePortalTypeClass(site, portal_type_name): ...@@ -269,73 +201,11 @@ def generatePortalTypeClass(site, portal_type_name):
property_sheet_generating_portal_type_set.add(portal_type_name) property_sheet_generating_portal_type_set.add(portal_type_name)
property_sheet_tool = getattr(site, 'portal_property_sheets', None)
property_sheet_name_set = set()
# The Property Sheet Tool may be None if the code is updated but
# the BT has not been upgraded yet with portal_property_sheets
if property_sheet_tool is None:
if not getattr(site, '_v_bootstrapping', False):
LOG("ERP5Type.dynamic", WARNING,
"Property Sheet Tool was not found. Please update erp5_core "
"Business Template")
zodb_property_sheet_name_set = set()
else:
zodb_property_sheet_name_set = set(property_sheet_tool.objectIds())
if portal_type is not None:
# Get the Property Sheets defined on the portal_type and use the
# ZODB Property Sheet rather than the filesystem
for property_sheet in portal_type.getTypePropertySheetList():
if property_sheet in zodb_property_sheet_name_set:
property_sheet_name_set.add(property_sheet)
# PDFTypeInformation document class, for example, defines a
# method which generates dynamically properties and this is
# heavily used by egov
update_definition_dict = getattr(portal_type,
'updatePropertySheetDefinitionDict',
None)
if update_definition_dict is not None and not \
update_definition_dict.__module__.startswith('Products.ERP5Type.ERP5Type'):
try:
update_definition_dict(attribute_dict)
except AttributeError:
pass
# Only kept for backward-compatibility as Preference and System
# Preference have Preference Type as portal type, which define
# getTypePropertySheetList properly and, likewise, Preference Tool
# has Preference Tool Type as its portal type
if portal_type_name in ("Preference Tool",
"Preference",
"System Preference"):
if portal_type is None or \
not portal_type.getPortalType().startswith(portal_type_name):
for property_sheet in zodb_property_sheet_name_set:
if property_sheet.endswith('Preference'):
property_sheet_name_set.add(property_sheet)
# Get the Property Sheets defined on the document and its bases
# recursively
from Products.ERP5Type.Base import getClassPropertyList
for property_sheet in getClassPropertyList(klass):
# If the Property Sheet is a string, then this is a ZODB
# Property Sheet
#
# NOTE: The Property Sheets of a document should be given as a
# string from now on
if not isinstance(property_sheet, basestring):
property_sheet = property_sheet.__name__
if property_sheet in zodb_property_sheet_name_set:
property_sheet_name_set.add(property_sheet)
if property_sheet_name_set:
# Initialize ZODB Property Sheets accessor holders # Initialize ZODB Property Sheets accessor holders
accessor_holder_list = _createAccessorHolderList(site, accessor_holder_list = createAllAccessorHolderList(site,
portal_type_name, portal_type_name,
property_sheet_name_set) portal_type,
klass)
base_category_set = set(attribute_dict['_categories']) base_category_set = set(attribute_dict['_categories'])
for accessor_holder in accessor_holder_list: for accessor_holder in accessor_holder_list:
...@@ -388,15 +258,29 @@ def initializeDynamicModules(): ...@@ -388,15 +258,29 @@ def initializeDynamicModules():
for example classes created through ClassTool that are in for example classes created through ClassTool that are in
$INSTANCE_HOME/Document $INSTANCE_HOME/Document
erp5.accessor_holder erp5.accessor_holder
holds accessors of ZODB Property Sheets holds accessor holders common to ZODB Property Sheets and Portal Types
erp5.accessor_holder.property_sheet
holds accessor holders of ZODB Property Sheets
erp5.accessor_holder.portal_type
holds accessors holders of Portal Types
""" """
erp5 = ModuleType("erp5") erp5 = ModuleType("erp5")
sys.modules["erp5"] = erp5 sys.modules["erp5"] = erp5
erp5.document = ModuleType("erp5.document") erp5.document = ModuleType("erp5.document")
sys.modules["erp5.document"] = erp5.document sys.modules["erp5.document"] = erp5.document
erp5.accessor_holder = ModuleType("erp5.accessor_holder") erp5.accessor_holder = AccessorHolderModuleType("erp5.accessor_holder")
sys.modules["erp5.accessor_holder"] = erp5.accessor_holder sys.modules["erp5.accessor_holder"] = erp5.accessor_holder
erp5.accessor_holder.property_sheet = \
AccessorHolderModuleType("erp5.accessor_holder.property_sheet")
sys.modules["erp5.accessor_holder.property_sheet"] = \
erp5.accessor_holder.property_sheet
erp5.accessor_holder.portal_type = registerDynamicModule(
'erp5.accessor_holder.portal_type',
AccessorHolderModuleType)
portal_type_container = registerDynamicModule('erp5.portal_type', portal_type_container = registerDynamicModule('erp5.portal_type',
generateLazyPortalTypeClass) generateLazyPortalTypeClass)
...@@ -502,10 +386,14 @@ def synchronizeDynamicModules(context, force=False): ...@@ -502,10 +386,14 @@ def synchronizeDynamicModules(context, force=False):
inspect.isclass): inspect.isclass):
klass.restoreGhostState() klass.restoreGhostState()
# Clear accessor holders of ZODB Property Sheets # Clear accessor holders of ZODB Property Sheets and Portal Types
for property_sheet_id in erp5.accessor_holder.__dict__.keys(): erp5.accessor_holder.clear()
if not property_sheet_id.startswith('__'): erp5.accessor_holder.property_sheet.clear()
delattr(erp5.accessor_holder, property_sheet_id)
for name in erp5.accessor_holder.portal_type.__dict__.keys():
if name[0] != '_':
delattr(erp5.accessor_holder.portal_type, name)
finally: finally:
Base.aq_method_lock.release() Base.aq_method_lock.release()
......
...@@ -595,14 +595,16 @@ class TestZodbPropertySheet(ERP5TypeTestCase): ...@@ -595,14 +595,16 @@ class TestZodbPropertySheet(ERP5TypeTestCase):
# The accessor holder will be generated once the new Person will # The accessor holder will be generated once the new Person will
# be created as Person type has test Property Sheet # be created as Person type has test Property Sheet
self.failIfHasAttribute(erp5.accessor_holder, 'TestMigration') self.failIfHasAttribute(erp5.accessor_holder.property_sheet,
'TestMigration')
new_person = portal.person_module.newContent( new_person = portal.person_module.newContent(
id='testAssignZodbPropertySheet', portal_type='Person') id='testAssignZodbPropertySheet', portal_type='Person')
self.assertHasAttribute(erp5.accessor_holder, 'TestMigration') self.assertHasAttribute(erp5.accessor_holder.property_sheet,
'TestMigration')
self.assertTrue(erp5.accessor_holder.TestMigration in \ self.assertTrue(erp5.accessor_holder.property_sheet.TestMigration in \
erp5.portal_type.Person.mro()) erp5.portal_type.Person.mro())
# Check that the accessors have been properly created for all # Check that the accessors have been properly created for all
...@@ -677,7 +679,7 @@ class TestZodbPropertySheet(ERP5TypeTestCase): ...@@ -677,7 +679,7 @@ class TestZodbPropertySheet(ERP5TypeTestCase):
new_person = portal.person_module.newContent( new_person = portal.person_module.newContent(
id='testAssignZodbPropertySheet', portal_type='Person') id='testAssignZodbPropertySheet', portal_type='Person')
self.failIfHasAttribute(erp5.accessor_holder, 'TestMigration') self.failIfHasAttribute(erp5.accessor_holder.property_sheet, 'TestMigration')
self.failIfHasAttribute(new_person, 'getTestStandardPropertyAssign') self.failIfHasAttribute(new_person, 'getTestStandardPropertyAssign')
finally: finally:
...@@ -687,15 +689,18 @@ class TestZodbPropertySheet(ERP5TypeTestCase): ...@@ -687,15 +689,18 @@ class TestZodbPropertySheet(ERP5TypeTestCase):
def _checkAddPropertyToZodbPropertySheet(self, def _checkAddPropertyToZodbPropertySheet(self,
new_property_function, new_property_function,
added_accessor_name): added_accessor_name):
import erp5.accessor_holder import erp5.accessor_holder.property_sheet
self.failIfHasAttribute(erp5.accessor_holder, 'TestMigration') self.failIfHasAttribute(erp5.accessor_holder.property_sheet,
'TestMigration')
new_property_function('add') new_property_function('add')
self._forceTestAccessorHolderGeneration() self._forceTestAccessorHolderGeneration()
self.assertHasAttribute(erp5.accessor_holder, 'TestMigration') self.assertHasAttribute(erp5.accessor_holder.property_sheet,
self.assertHasAttribute(erp5.accessor_holder.TestMigration, 'TestMigration')
self.assertHasAttribute(erp5.accessor_holder.property_sheet.TestMigration,
added_accessor_name) added_accessor_name)
def testAddStandardPropertyToZodbPropertySheet(self): def testAddStandardPropertyToZodbPropertySheet(self):
...@@ -738,15 +743,18 @@ class TestZodbPropertySheet(ERP5TypeTestCase): ...@@ -738,15 +743,18 @@ class TestZodbPropertySheet(ERP5TypeTestCase):
change_setter_func, change_setter_func,
new_value, new_value,
changed_accessor_name): changed_accessor_name):
import erp5.accessor_holder import erp5.accessor_holder.property_sheet
self.failIfHasAttribute(erp5.accessor_holder, 'TestMigration') self.failIfHasAttribute(erp5.accessor_holder.property_sheet,
'TestMigration')
change_setter_func(new_value) change_setter_func(new_value)
self._forceTestAccessorHolderGeneration() self._forceTestAccessorHolderGeneration()
self.assertHasAttribute(erp5.accessor_holder, 'TestMigration') self.assertHasAttribute(erp5.accessor_holder.property_sheet,
self.assertHasAttribute(erp5.accessor_holder.TestMigration, 'TestMigration')
self.assertHasAttribute(erp5.accessor_holder.property_sheet.TestMigration,
changed_accessor_name) changed_accessor_name)
def testChangeStandardPropertyOfZodbPropertySheet(self): def testChangeStandardPropertyOfZodbPropertySheet(self):
...@@ -798,7 +806,7 @@ class TestZodbPropertySheet(ERP5TypeTestCase): ...@@ -798,7 +806,7 @@ class TestZodbPropertySheet(ERP5TypeTestCase):
Delete the given property from the test Property Sheet and check Delete the given property from the test Property Sheet and check
whether its corresponding accessor is not there anymore whether its corresponding accessor is not there anymore
""" """
import erp5.accessor_holder import erp5.accessor_holder.property_sheet
self.failIfHasAttribute(erp5.accessor_holder, 'TestMigration') self.failIfHasAttribute(erp5.accessor_holder, 'TestMigration')
...@@ -807,8 +815,8 @@ class TestZodbPropertySheet(ERP5TypeTestCase): ...@@ -807,8 +815,8 @@ class TestZodbPropertySheet(ERP5TypeTestCase):
self.test_property_sheet.deleteContent(property_id) self.test_property_sheet.deleteContent(property_id)
self._forceTestAccessorHolderGeneration() self._forceTestAccessorHolderGeneration()
self.assertHasAttribute(erp5.accessor_holder, 'TestMigration') self.assertHasAttribute(erp5.accessor_holder.property_sheet, 'TestMigration')
self.failIfHasAttribute(erp5.accessor_holder.TestMigration, self.failIfHasAttribute(erp5.accessor_holder.property_sheet.TestMigration,
accessor_name) accessor_name)
def testDeleteStandardPropertyFromZodbPropertySheet(self): def testDeleteStandardPropertyFromZodbPropertySheet(self):
......
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