Commit 9c408f22 authored by Arnaud Fontaine's avatar Arnaud Fontaine

WIP: ZODB Components: Likewise Document, add Mixin (erp5.component.mixin) and...

WIP: ZODB Components: Likewise Document, add Mixin (erp5.component.mixin) and Interface (erp5.component.interface).

* One Mixin/Interface class per ZODB Component.
  => Already the case for FS Mixin, not for Interfaces.
* ZODB Components module name ('reference' property) and class name:
  + Mixin: FooMixin.
  + Interface: IFoo.

Rationale:
  + Avoid current FS hacks: registry (Mixins, mixin_class_registry) or import
    all classes explicitly in __init__.py (Products.ERP5Type.interfaces).
  + Consistent naming.
  + Consistent with ZODB Documents Components.

TODO BEFORE MERGING:
  + Add Unit Tests.
parent ba3ad323
......@@ -1160,6 +1160,14 @@ class ObjectTemplateItem(BaseTemplateItem):
"""
pass
def afterUninstall(self):
"""
Uninstallation hook.
Called right before returning in "uninstall" method.
Can be overridden by subclasses.
"""
pass
def onNewObject(self, obj):
"""
Installation hook.
......@@ -1642,6 +1650,7 @@ class ObjectTemplateItem(BaseTemplateItem):
# object is already backup and/or removed
pass
BaseTemplateItem.uninstall(self, context, **kw)
self.afterUninstall()
class PathTemplateItem(ObjectTemplateItem):
"""
......@@ -3795,7 +3804,7 @@ class ModuleTemplateItem(BaseTemplateItem):
pass
# XXX-arnau: when everything has been migrated to Components, this class
# should be renamed to DocumentTemplateItem
# should be removed and only _ZodbComponentTemplateItem should remain
class FilesystemDocumentTemplateItem(BaseTemplateItem):
local_file_reader_name = staticmethod(readLocalDocument)
local_file_writer_name = staticmethod(writeLocalDocument)
......@@ -4003,12 +4012,6 @@ class FilesystemToZodbTemplateItem(FilesystemDocumentTemplateItem,
return FilesystemDocumentTemplateItem._importFile(self, file_name,
*args, **kw)
def afterUninstall(self, already_migrated=False):
"""
Hook called after uninstall
"""
pass
def uninstall(self, *args, **kw):
# Only for uninstall, the path of objects can be given as a
# parameter, otherwise it fallbacks on '_archive'
......@@ -4018,14 +4021,11 @@ class FilesystemToZodbTemplateItem(FilesystemDocumentTemplateItem,
else:
object_keys = self._archive.keys()
already_migrated = self._is_already_migrated(object_keys)
if already_migrated:
if self._is_already_migrated(object_keys):
ObjectTemplateItem.uninstall(self, *args, **kw)
else:
FilesystemDocumentTemplateItem.uninstall(self, *args, **kw)
self.afterUninstall(already_migrated)
def remove(self, context, **kw):
"""
Conversion of magically uniqued paths to real ones
......@@ -4207,9 +4207,71 @@ class ConstraintTemplateItem(FilesystemDocumentTemplateItem):
local_file_importer_name = staticmethod(importLocalConstraint)
local_file_remover_name = staticmethod(removeLocalConstraint)
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
class _ZodbComponentTemplateItem(ObjectTemplateItem):
@staticmethod
def _getZodbObjectId(id):
raise NotImplementedError
def isKeepWorkflowObjectLastHistoryOnly(self, path):
"""
Component Validation Workflow last History of ZODB Components must always be
kept, without explicitly adding them to the field which requires an extra
action for developers
"""
return True
def _removeAllButLastWorkflowHistory(self, obj):
"""
Only export the last state of component_validation_workflow, because only
the source code and its state to load it is necessary for ZODB Components
and too much history would be exported (edit_workflow)
"""
for wf_id in obj.workflow_history.keys():
if wf_id != 'component_validation_workflow':
del obj.workflow_history[wf_id]
continue
wf_history = obj.workflow_history[wf_id][-1]
# Remove useless modifcation 'time' and 'actor' (conflicts with VCSs)
wf_history.pop('time', None)
wf_history.pop('actor', None)
wf_history.pop('comment', None)
obj.workflow_history[wf_id] = WorkflowHistoryList([wf_history])
def afterInstall(self):
"""
Reset component on the fly, because it is possible that those components
are required in the middle of the transaction. For example:
- A method in a component is called while installing.
- A document component is used in a different business template, and
those business templates are installed in a single transaction by
upgrader.
class DocumentTemplateItem(FilesystemToZodbTemplateItem):
This reset is called at most 3 times in one business template
installation. (for Document, Test, Extension)
"""
self.portal_components.reset(force=True)
def afterUninstall(self):
self.portal_components.reset(force=True,
reset_portal_type_at_transaction_boundary=True)
from Products.ERP5Type.Core.InterfaceComponent import InterfaceComponent
class InterfaceTemplateItem(_ZodbComponentTemplateItem):
@staticmethod
def _getZodbObjectId(id):
return InterfaceComponent.getIdPrefix() + '.' + id
from Products.ERP5Type.Core.MixinComponent import MixinComponent
class MixinTemplateItem(_ZodbComponentTemplateItem):
@staticmethod
def _getZodbObjectId(id):
return MixinComponent.getIdPrefix() + '.' + id
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
class DocumentTemplateItem(FilesystemToZodbTemplateItem,
_ZodbComponentTemplateItem):
"""
Documents are now stored in ZODB rather than on the filesystem. However,
some Business Templates may still have filesystem Documents which need to be
......@@ -4230,12 +4292,14 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem):
This allows to keep Git history and having readable source code instead of
being crippled into an XML file
"""
_tool_id = 'portal_components'
@staticmethod
def _getZodbObjectId(id):
return DocumentComponent.getIdPrefix() + '.' + id
## All the methods/attributes below are for FS compatibility *only* and
## should be removed when all bt5s have been migrated
_tool_id = 'portal_components'
@staticmethod
def _getFilesystemPath(class_id):
from App.config import getConfiguration
......@@ -4251,25 +4315,6 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem):
"""
return path.startswith(self._tool_id + '/')
def _removeAllButLastWorkflowHistory(self, obj):
"""
Only export the last state of component_validation_workflow, because only
the source code and its state to load it is necessary for ZODB Components
and too much history would be exported (edit_workflow)
"""
for wf_id in obj.workflow_history.keys():
if wf_id != 'component_validation_workflow':
del obj.workflow_history[wf_id]
continue
wf_history = obj.workflow_history[wf_id][-1]
# Remove useless modifcation 'time' and 'actor' (conflicts with VCSs)
wf_history.pop('time', None)
wf_history.pop('actor', None)
wf_history.pop('comment', None)
obj.workflow_history[wf_id] = WorkflowHistoryList([wf_history])
# XXX temporary should be eliminated from here
def _importFile(self, file_name, file_obj):
ObjectTemplateItem._importFile(self, file_name, file_obj)
......@@ -4289,6 +4334,7 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem):
if not self._archive:
return
# After running the migration script, update bt5 property accordingly
if not self._is_already_migrated(self._archive.keys()):
document_id_list = self.getTemplateIdList()
if document_id_list[0] not in getattr(context.getPortalObject(),
......@@ -4307,23 +4353,16 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem):
issue as there are not so many Documents in bt5...
"""
if self._is_already_migrated(self._objects.keys()):
ObjectTemplateItem.install(self, context, **kw)
# Reset component on the fly, because it is possible that those
# components are required in the middle of the transaction. For example:
# - A method in a component is called while installing.
# - A document component is used in a different business template,
# and those business templates are installed in a single transaction
# by upgrader.
# This reset is called at most 3 times in one business template
# installation. (for Document, Test, Extension)
self.portal_components.reset(force=True)
_ZodbComponentTemplateItem.install(self, context, **kw)
else:
FilesystemDocumentTemplateItem.install(self, context, **kw)
def afterUninstall(self, already_migrated=False):
if already_migrated:
self.portal_components.reset(force=True,
reset_portal_type_at_transaction_boundary=True)
_removeAllButLastWorkflowHistory = _ZodbComponentTemplateItem._removeAllButLastWorkflowHistory
# Only for ObjectTemplateItem (ZODB Components) and thus no need to check
# whether they have already been migrated or not
afterInstall = _ZodbComponentTemplateItem.afterInstall
afterUninstall = _ZodbComponentTemplateItem.afterUninstall
from Products.ERP5Type.Core.ExtensionComponent import ExtensionComponent
......@@ -5117,6 +5156,10 @@ Business Template is a set of definitions, such as skins, portal types and categ
ModuleTemplateItem(self.getTemplateModuleIdList())
self._document_item = \
DocumentTemplateItem(self.getTemplateDocumentIdList())
self._interface_item = \
InterfaceTemplateItem(self.getTemplateInterfaceIdList())
self._mixin_item = \
MixinTemplateItem(self.getTemplateMixinIdList())
self._property_sheet_item = \
PropertySheetTemplateItem(self.getTemplatePropertySheetIdList(),
context=self)
......@@ -5938,6 +5981,8 @@ Business Template is a set of definitions, such as skins, portal types and categ
'PropertySheet' : '_property_sheet_item',
'Constraint' : '_constraint_item',
'Document' : '_document_item',
'Interface': '_interface_item',
'Mixin': '_mixin_item',
'Extension' : '_extension_item',
'Test' : '_test_item',
'Role' : '_role_item',
......@@ -6048,7 +6093,8 @@ Business Template is a set of definitions, such as skins, portal types and categ
# Text objects (no need to export them into XML)
# XXX Bad naming
item_list_3 = ['_document_item', '_property_sheet_item',
item_list_3 = ['_document_item', '_interface_item', '_mixin_item',
'_property_sheet_item',
'_constraint_item', '_extension_item',
'_test_item', '_message_translation_item',]
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_view</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_view</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>view</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>1.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>View</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/ComponentMixin_view</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>python: object is not None and not object.isWebMode()</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_view</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_view</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>view</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>1.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>View</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/ComponentMixin_view</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>python: object is not None and not object.isWebMode()</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -51,6 +51,8 @@
<portal_type id="Component Tool">
<item>Document Component</item>
<item>Extension Component</item>
<item>Interface Component</item>
<item>Mixin Component</item>
<item>Test Component</item>
</portal_type>
<portal_type id="Contribution Registry Tool">
......
......@@ -41,6 +41,12 @@
<portal_type id="Extension Component">
<item>SortIndex</item>
</portal_type>
<portal_type id="Interface Component">
<item>SortIndex</item>
</portal_type>
<portal_type id="Mixin Component">
<item>SortIndex</item>
</portal_type>
<portal_type id="Property Existence Constraint">
<item>ConstraintType</item>
</portal_type>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Type" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_property_domain_dict</string> </key>
<value>
<dictionary>
<item>
<key> <string>short_title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>acquire_local_roles</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>content_icon</string> </key>
<value> <string>web_page.png</string> </value>
</item>
<item>
<key> <string>content_meta_type</string> </key>
<value> <string>ERP5 Text Document</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>An Interface Component is just a specific Document Component for Zope Interfaces in ZODB. </string> </value>
</item>
<item>
<key> <string>factory</string> </key>
<value> <string>addDocumentComponent</string> </value>
</item>
<item>
<key> <string>filter_content_types</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Interface Component</string> </value>
</item>
<item>
<key> <string>init_script</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>type_class</string> </key>
<value> <string>InterfaceComponent</string> </value>
</item>
<item>
<key> <string>type_interface</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>domain_name</string> </key>
<value> <string>erp5_content</string> </value>
</item>
<item>
<key> <string>property_name</string> </key>
<value> <string>short_title</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<tuple>
<global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>domain_name</string> </key>
<value> <string>erp5_content</string> </value>
</item>
<item>
<key> <string>property_name</string> </key>
<value> <string>title</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Type" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_property_domain_dict</string> </key>
<value>
<dictionary>
<item>
<key> <string>short_title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>acquire_local_roles</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>content_icon</string> </key>
<value> <string>web_page.png</string> </value>
</item>
<item>
<key> <string>content_meta_type</string> </key>
<value> <string>ERP5 Text Document</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>A Mixin Component is just a specific Document Component for ERP5 mixins in ZODB. </string> </value>
</item>
<item>
<key> <string>factory</string> </key>
<value> <string>addDocumentComponent</string> </value>
</item>
<item>
<key> <string>filter_content_types</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Mixin Component</string> </value>
</item>
<item>
<key> <string>init_script</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>type_class</string> </key>
<value> <string>MixinComponent</string> </value>
</item>
<item>
<key> <string>type_interface</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>domain_name</string> </key>
<value> <string>erp5_content</string> </value>
</item>
<item>
<key> <string>property_name</string> </key>
<value> <string>short_title</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<tuple>
<global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>domain_name</string> </key>
<value> <string>erp5_content</string> </value>
</item>
<item>
<key> <string>property_name</string> </key>
<value> <string>title</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -107,6 +107,10 @@
<type>Extension Component</type>
<workflow>component_validation_workflow, dynamic_class_generation_interaction_workflow, edit_workflow</workflow>
</chain>
<chain>
<type>Interface Component</type>
<workflow>component_validation_workflow, dynamic_class_generation_interaction_workflow, edit_workflow</workflow>
</chain>
<chain>
<type>Mapped Value</type>
<workflow>edit_workflow</workflow>
......@@ -115,6 +119,10 @@
<type>Memcached Plugin</type>
<workflow>memcached_plugin_interaction_workflow</workflow>
</chain>
<chain>
<type>Mixin Component</type>
<workflow>component_validation_workflow, dynamic_class_generation_interaction_workflow, edit_workflow</workflow>
</chain>
<chain>
<type>Predicate</type>
<workflow>edit_workflow</workflow>
......
......@@ -64,6 +64,8 @@
<list>
<string>my_template_role_list</string>
<string>my_template_site_property_id_list</string>
<string>my_template_interface_id_list</string>
<string>my_template_mixin_id_list</string>
<string>my_template_document_id_list</string>
<string>my_template_property_sheet_id_list</string>
<string>my_template_extension_id_list</string>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="LinesField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>my_template_interface_id_list</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
<item>
<key> <string>line_too_long</string> </key>
<value> <string>A line was too long.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
<item>
<key> <string>too_long</string> </key>
<value> <string>You entered too many characters.</string> </value>
</item>
<item>
<key> <string>too_many_lines</string> </key>
<value> <string>You entered too many lines.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>view_separator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>view_separator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Interface Classes</string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>view_separator</string> </key>
<value> <string encoding="cdata"><![CDATA[
<br />
]]></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>40</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="LinesField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>my_template_mixin_id_list</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
<item>
<key> <string>line_too_long</string> </key>
<value> <string>A line was too long.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
<item>
<key> <string>too_long</string> </key>
<value> <string>You entered too many characters.</string> </value>
</item>
<item>
<key> <string>too_many_lines</string> </key>
<value> <string>You entered too many lines.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>view_separator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>view_separator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Mixin Classes</string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>view_separator</string> </key>
<value> <string encoding="cdata"><![CDATA[
<br />
]]></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>40</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -72,6 +72,8 @@
<list>
<string>Document Component</string>
<string>Extension Component</string>
<string>Interface Component</string>
<string>Mixin Component</string>
<string>Test Component</string>
</list>
</value>
......
......@@ -71,10 +71,18 @@
<list>
<string>Document Component</string>
<string>Extension Component</string>
<string>Interface Component</string>
<string>Mixin Component</string>
<string>Test Component</string>
</list>
</value>
</item>
<item>
<key> <string>portal_type_group_filter</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>script_name</string> </key>
<value>
......
......@@ -85,8 +85,10 @@ Dynamic Category Property | view
Extension Component | view
Folder | view
Id Tool | view
Interface Component | view
Memcached Plugin | view
Memcached Tool | view
Mixin Component | view
Predicate | view
Preference Tool Type | jump_property_sheets
Preference Tool Type | view
......
......@@ -21,6 +21,8 @@ Category Tool | Base Category
Category | Category
Component Tool | Document Component
Component Tool | Extension Component
Component Tool | Interface Component
Component Tool | Mixin Component
Component Tool | Test Component
Contribution Registry Tool | Contribution Predicate
Domain Tool | Base Domain
......
......@@ -48,9 +48,11 @@ Event
Extension Component
Folder
Id Tool
Interface Component
Mapped Value
Memcached Plugin
Memcached Tool
Mixin Component
Movement
Notification Tool
Order Tool
......
......@@ -12,6 +12,8 @@ Category Related Membership State Constraint | ConstraintType
Content Existence Constraint | ConstraintType
Document Component | SortIndex
Extension Component | SortIndex
Interface Component | SortIndex
Mixin Component | SortIndex
Property Existence Constraint | ConstraintType
Property Type Validity Constraint | ConstraintType
Python Script | CatalogFilter
......
......@@ -32,8 +32,14 @@ Dynamic Category Property | dynamic_class_generation_interaction_workflow
Extension Component | component_validation_workflow
Extension Component | dynamic_class_generation_interaction_workflow
Extension Component | edit_workflow
Interface Component | component_validation_workflow
Interface Component | dynamic_class_generation_interaction_workflow
Interface Component | edit_workflow
Mapped Value | edit_workflow
Memcached Plugin | memcached_plugin_interaction_workflow
Mixin Component | component_validation_workflow
Mixin Component | dynamic_class_generation_interaction_workflow
Mixin Component | edit_workflow
Predicate | edit_workflow
Preference | edit_workflow
Preference | preference_workflow
......
<?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>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<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 ids of Interfaces used by this template</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>template_interface_id_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</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>
<?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>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<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 ids of Mixins used by this template</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>template_mixin_id_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</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>
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2018 Nexedi SA and Contributors. All Rights Reserved.
# Arnaud Fontaine <arnaud.fontaine@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
class InterfaceComponent(DocumentComponent):
"""
ZODB Component for interfaces
"""
meta_type = 'ERP5 Interface Component'
portal_type = 'Interface Component'
@staticmethod
def _getDynamicModuleNamespace():
return 'erp5.component.interface'
@staticmethod
def getIdPrefix():
return 'interface'
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2018 Nexedi SA and Contributors. All Rights Reserved.
# Arnaud Fontaine <arnaud.fontaine@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
class MixinComponent(DocumentComponent):
"""
ZODB Component for mixins
"""
meta_type = 'ERP5 Mixin Component'
portal_type = 'Mixin Component'
@staticmethod
def _getDynamicModuleNamespace():
return 'erp5.component.mixin'
@staticmethod
def getIdPrefix():
return 'mixin'
......@@ -200,36 +200,6 @@ class TypesTool(TypeProvider):
return None
return getattr(self, portal_type, None)
security.declareProtected(Permissions.AccessContentsInformation, 'getDocumentTypeList')
def getDocumentTypeList(self):
"""
Return a list of Document types (including filesystem and ZODB Component
Documents) that can be used as Base classes
"""
from Products.ERP5Type import document_class_registry
document_type_set = set(document_class_registry)
import erp5.component.document
portal = self.getPortalObject()
version_priority_set = set(portal.getVersionPriorityNameList())
# objectValues should not be used for a large number of objects, but
# this is only done upon reset, moreover using the Catalog is too risky
# as it lags behind and depends upon objects being reindexed
for component in portal.portal_components.objectValues(portal_type='Document Component'):
# Only consider modified or validated states as state transition will
# be handled by component_validation_workflow which will take care of
# updating the registry
validation_state_tuple = component.getValidationState()
if validation_state_tuple in ('modified', 'validated'):
version = component.getVersion(validated_only=True)
# The versions should have always been set on ERP5Site property
# beforehand
if version in version_priority_set:
document_type_set.add(component.getReference(validated_only=True))
return sorted(document_type_set)
security.declareProtected(Permissions.AccessContentsInformation, 'getPortalTypeClass')
def getPortalTypeClass(self, context, temp=False):
"""
......@@ -258,13 +228,44 @@ class TypesTool(TypeProvider):
module = erp5.portal_type
return getattr(module, portal_type, None)
def _getTypeList(self, component_portal_type, fs_type_list):
portal = self.getPortalObject()
version_priority_set = set(portal.getVersionPriorityNameList())
# objectValues should not be used for a large number of objects, but
# this is only done upon reset, moreover using the Catalog is too risky
# as it lags behind and depends upon objects being reindexed
type_set = set(fs_type_list)
for component in portal.portal_components.objectValues(portal_type=component_portal_type):
# Only consider modified or validated states as state transition will
# be handled by component_validation_workflow which will take care of
# updating the registry
validation_state_tuple = component.getValidationState()
if validation_state_tuple in ('modified', 'validated'):
version = component.getVersion(validated_only=True)
# The versions should have always been set on ERP5Site property
# beforehand
if version in version_priority_set:
type_set.add(component.getReference(validated_only=True))
return sorted(type_set)
security.declareProtected(Permissions.AccessContentsInformation, 'getDocumentTypeList')
def getDocumentTypeList(self):
"""
Return a list of Document types (including filesystem and ZODB Component
Documents) that can be used as Base classes
"""
from Products.ERP5Type import document_class_registry
return self._getTypeList('Document Component', document_class_registry)
security.declareProtected(Permissions.AccessContentsInformation, 'getMixinTypeList')
def getMixinTypeList(self):
"""
Return a list of class names that can be used as Mixins
"""
from Products.ERP5Type import mixin_class_registry
return sorted(mixin_class_registry)
return self._getTypeList('Mixin Component', mixin_class_registry)
security.declareProtected(Permissions.AccessContentsInformation, 'getInterfaceTypeList')
def getInterfaceTypeList(self):
......@@ -272,7 +273,9 @@ class TypesTool(TypeProvider):
Return a list of class names that can be used as Interfaces
"""
from Products.ERP5Type import interfaces
return [name for name, cls in inspect.getmembers(interfaces, inspect.isclass)]
return self._getTypeList(
'Interface Component',
[name for name, _ in inspect.getmembers(interfaces, inspect.isclass)])
security.declareProtected(Permissions.ModifyPortalContent,
'resetDynamicDocumentsOnceAtTransactionBoundary')
......
......@@ -182,6 +182,10 @@ def initializeDynamicModules():
holds ZODB Component packages
erp5.component.document:
holds Document modules previously found in bt5 in $INSTANCE_HOME/Document
erp5.component.interface:
holds Interface modules previously found in Products.NAME.interfaces
erp5.component.mixin:
holds Mixin modules previously found in Products.NAME.mixin
erp5.component.extension:
holds Extension modules previously found in bt5 in
$INSTANCE_HOME/Extensions
......@@ -236,6 +240,12 @@ def initializeDynamicModules():
erp5.component.document = ComponentDynamicPackage('erp5.component.document',
'Document Component')
erp5.component.interface = ComponentDynamicPackage('erp5.component.interface',
'Interface Component')
erp5.component.mixin = ComponentDynamicPackage('erp5.component.mixin',
'Mixin Component')
erp5.component.test = ComponentDynamicPackage('erp5.component.test',
'Test Component')
finally:
......
......@@ -201,9 +201,8 @@ def generatePortalTypeClass(site, portal_type_name):
klass = getattr(module, type_class)
except AttributeError:
LOG("ERP5Type.dynamic", WARNING,
"Could not get class '%s' in Component module '%s'" % \
(type_class,
module))
"Could not get class '%s' in Component module %r, fallback on filesystem" %
(type_class, module))
if klass is None:
type_class_path = document_class_registry.get(type_class)
......@@ -244,18 +243,58 @@ def generatePortalTypeClass(site, portal_type_name):
# "Filled accessor holder list for portal_type %s (%s)" % \
# (portal_type_name, accessor_holder_list))
mixin_path_list = []
mixin_class_list = []
if mixin_list:
mixin_path_list = map(mixin_class_registry.__getitem__, mixin_list)
mixin_class_list = map(_importClass, mixin_path_list)
# Only one Mixin class per ZODB Component (!= FS) where module_name ==
# class_name, name ending with 'Mixin'.
#
# Rationale: same as Document/Interface; consistent naming; avoid a
# registry like there used to be with FS.
import erp5.component.mixin
for mixin in mixin_list:
mixin_module = erp5.component.mixin.find_load_module(mixin)
mixin_class = None
if mixin_module is not None:
try:
mixin_class = getattr(mixin_module, mixin)
except AttributeError:
LOG("ERP5Type.dynamic", WARNING,
"Could not get class '%s' in Component module %r, fallback on filesystem" %
(mixin, mixin_module))
if mixin_class is None:
mixin_class = _importClass(mixin_class_registry[mixin])
mixin_class_list.append(mixin_class)
base_class_list = [klass] + accessor_holder_list + mixin_class_list
interface_class_list = []
if interface_list:
from Products.ERP5Type import interfaces
interface_class_list = [getattr(interfaces, name)
for name in interface_list]
# Filesystem Interfaces may have defined several Interfaces in one file
# but only *one* Interface per ZODB Component where module_name ==
# class_name, name starting with 'I'.
#
# Rationale: same as Document/Mixin; consistent naming; avoid a registry
# like there used to be for Mixin or importing all class in
# Products.ERP5Type.interfaces.__init__.py.
import erp5.component.interface
from Products.ERP5Type import interfaces as filesystem_interfaces
for interface in interface_list:
interface_module = erp5.component.interface.find_load_module(interface)
interface_class = None
if interface_module is not None:
try:
interface_class = getattr(interface_module, interface)
except AttributeError:
LOG("ERP5Type.dynamic", WARNING,
"Could not get class '%s' in Component module %r, fallback on filesystem" %
(interface, interface_module))
if interface_class is None:
interface_class = getattr(filesystem_interfaces, interface)
interface_class_list.append(interface_class)
if portal_type_name in core_portal_type_class_dict:
core_portal_type_class_dict[portal_type_name]['generating'] = False
......
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