[CMF-checkins] CVS: CMF/CMFSetup - typeinfo.py:1.3
Tres Seaver
tseaver at zope.com
Sat May 29 23:55:35 EDT 2004
Update of /cvs-repository/CMF/CMFSetup
In directory cvs.zope.org:/tmp/cvs-serv17007
Modified Files:
typeinfo.py
Log Message:
- typeinfo.py:
o Move import code for types over; test underlying layers.
o N.B.: Top-level entry points, 'importTypesTool' and
'exportTypesTool', are not yet tested.
- tests/test_skins.py:
o Make test name clearer.
- tests/test_typeinfo.py:
o Remove XXX note on design issue: today's changes are all to
resolve it in favor of Doing the Right Thing (TM).
=== CMF/CMFSetup/typeinfo.py 1.2 => 1.3 ===
--- CMF/CMFSetup/typeinfo.py:1.2 Sat May 29 19:44:53 2004
+++ CMF/CMFSetup/typeinfo.py Sat May 29 23:55:04 2004
@@ -11,12 +11,72 @@
from Products.CMFCore.TypesTool import FactoryTypeInformation
from Products.CMFCore.TypesTool import ScriptableTypeInformation
+from Products.CMFCore.TypesTool import typeClasses
from Products.CMFCore.utils import getToolByName
from permissions import ManagePortal
from utils import HandlerBase
from utils import _xmldir
+#
+# Entry points
+#
+_TOOL_FILENAME = 'typestool.xml'
+
+def importTypesTool( context ):
+
+ """ Import types tool and content types from XML files.
+ """
+ site = context.getSite()
+ encoding = context.getEncoding()
+
+ types_tool = getToolByName( site, 'portal_types' )
+ #if config_file is None:
+ # config_file = context.getDataFile('types.xml')
+
+ if context.shouldPurge():
+
+ for type in types_tool.objectIds():
+ types_tool._delObject(type)
+
+ configurator = TypeInfoConfigurator( site )
+ text = context.readDataFile( _TOOL_FILENAME )
+
+ for type_id in configurator.parseToolXML( text ):
+
+ type_filename = _getTypeFilename( type_id )
+ text = context.readDataFile( type_filename )
+ configurator.parseTypeXML( text )
+
+
+ # XXX: YAGNI?
+ # importScriptsToContainer(types_tool, ('typestool_scripts',),
+ # context)
+
+ return 'Type tool imported'
+
+def exportTypesTool( context ):
+
+ """ Export types tool content types as a set of XML files.
+ """
+ site = context.getSite()
+ types_tool = getToolByName( site, 'portal_types' )
+ configurator = TypeInfoConfigurator( site ).__of__( site )
+
+ tool_xml = configurator.generateToolXML()
+ context.writeDataFile( _TOOL_FILENAME, tool_xml )
+
+ for type_id in types_tool.listContentTypes():
+
+ type_filename = _getTypeFilename( type_id )
+ type_xml = configurator.generateTypeXML( type_id )
+ context.writeDataFile( type_filename, type_xml )
+
+ # XXX: YAGNI?
+ # exportScriptsFromContainer(types_tool, ('typestool_scripts',))
+
+ return 'Types tool exported'
+
class TypeInfoConfigurator( Implicit ):
security = ClassSecurityInfo()
@@ -77,6 +137,33 @@
"""
return self._typeConfig( type_id=type_id )
+ security.declareProtected( ManagePortal, 'parseToolXML' )
+ def parseToolXML( self, xml, encoding=None ):
+
+ """ Pseudo API.
+ """
+ parser = _TypesToolParser( encoding )
+ parseString( xml, parser )
+ return parser._types
+
+ security.declareProtected( ManagePortal, 'parseTypeXML' )
+ def parseTypeXML( self, xml, encoding=None ):
+
+ """ Pseudo API.
+ """
+ tool = getToolByName( self._site, 'portal_types' )
+ parser = _TypeInfoParser( encoding )
+ parseString( xml, parser )
+
+ for info in parser._info_list:
+
+ klass_info = [ x for x in typeClasses
+ if x[ 'name' ] == info[ 'kind' ] ][ 0 ]
+
+ type_info = klass_info[ 'class' ]( **info )
+
+ tool._setObject( info[ 'id' ], type_info )
+
#
# Helper methods
#
@@ -110,6 +197,10 @@
, 'aliases' : ti.getMethodAliases()
}
+ if ' ' in ti.getId():
+
+ result[ 'filename' ] = ti.getId().replace( ' ', '_' )
+
if isinstance( ti, FactoryTypeInformation ):
result[ 'kind' ] = FactoryTypeInformation.meta_type
@@ -143,3 +234,153 @@
}
InitializeClass( TypeInfoConfigurator )
+
+class _TypesToolParser( HandlerBase ):
+
+ security = ClassSecurityInfo()
+
+ def __init__( self, encoding ):
+
+ self._encoding = encoding
+ self._types = []
+
+ security.declarePrivate( 'startElement' )
+ def startElement( self, name, attrs ):
+
+ if name == 'types-tool':
+ pass
+
+ if name == 'type':
+
+ id = self._extract( attrs, 'id' )
+ filename = self._extract( attrs, 'filename', id )
+ filename = _getTypeFilename( filename )
+
+ self._types.append( ( id, filename ) )
+
+InitializeClass( _TypesToolParser )
+
+_TYPE_INTS = ['global_allow', 'filter_content_types', 'allow_discussion']
+
+class _TypeInfoParser( HandlerBase ):
+
+ security = ClassSecurityInfo()
+
+ def __init__( self, encoding ):
+
+ self._encoding = encoding
+ self._info_list = []
+ self._description = None
+
+ security.declarePrivate( 'startElement' )
+ def startElement( self, name, attrs ):
+
+ def _es( key, default=None ):
+ return self._extract( attrs, key, default )
+
+ def _eb( key, default=None ):
+ return self._extractBoolean( attrs, key, default )
+
+ if name == 'type-info':
+
+ type_id = _es( 'id' )
+ kind = _es( 'kind' )
+ title = _es( 'title', type_id )
+ meta_type = _es( 'meta_type', type_id )
+ icon = _es( 'icon', '%s.png' % type_id )
+ immediate_view = _es( 'icon', '%s_edit' % type_id )
+ global_allow = _eb( 'global_allow', True )
+ filter_content_types = _eb( 'filter_content_types', False )
+ allowed_content_types = _es( 'allowed_content_types', '' )
+ allowed_content_types = allowed_content_types.split( ',' )
+ allow_discussion = _eb( 'allow_discussion', False )
+
+ info = { 'id' : type_id
+ , 'kind' : kind
+ , 'title' : title
+ , 'description' : ''
+ , 'meta_type' : meta_type
+ , 'icon' : icon
+ , 'immediate_view' : immediate_view
+ , 'global_allow' : global_allow
+ , 'filter_content_types' : filter_content_types
+ , 'allowed_content_types' : allowed_content_types
+ , 'allow_discussion' : allow_discussion
+ , 'aliases' : {}
+ , 'actions' : []
+ }
+
+ if kind == FactoryTypeInformation.meta_type:
+
+ info[ 'product' ] = _es( 'product' )
+ info[ 'factory' ] = _es( 'factory' )
+
+ elif kind == ScriptableTypeInformation.meta_type:
+
+ info[ 'constructor_path' ] = _es( 'constructor_path' )
+ info[ 'permission' ] = _es( 'permission' )
+
+ self._info_list.append( info )
+
+ elif name == 'aliases':
+ pass
+
+ elif name == 'alias':
+
+ t_info = self._info_list[ -1 ]
+ alias_from = _es( 'from' )
+ alias_to = _es( 'to' )
+
+ t_info[ 'aliases' ][ alias_from ] = alias_to
+
+ elif name == 'action':
+
+ t_info = self._info_list[ -1 ]
+ a_info = { 'id' : _es( 'action_id' )
+ , 'title' : _es( 'title' )
+ , 'action' : _es( 'action_expr' )
+ , 'condition' : _es( 'condition' )
+ , 'permissions' : _es( 'permissions' ).split( ',' )
+ , 'category' : _es( 'category' )
+ , 'visible' : _eb( 'visible' )
+ }
+
+ t_info[ 'actions' ].append( a_info )
+
+ elif name == 'description':
+ self._description = ''
+
+ else:
+ raise ValueError, 'Unknown element %s' % name
+
+ security.declarePrivate('endElement')
+ def endElement(self, name):
+
+ if name == 'description':
+
+ info = self._info_list[ -1 ]
+ info[ 'description' ] = _cleanDescription( self._description )
+ self._description = None
+
+ security.declarePrivate( 'characters' )
+ def characters( self, chars ):
+
+ if self._description is not None:
+
+ if self._encoding:
+ chars = chars.encode( self._encoding )
+
+ self._description += chars
+
+
+InitializeClass( _TypeInfoParser )
+
+def _getTypeFilename( type_id ):
+
+ """ Return the name of the file which holds info for a given type.
+ """
+ return 'types/%s.xml' % type_id
+
+def _cleanDescription( desc ):
+
+ return ''.join( map( lambda x: x.lstrip(), desc.splitlines( 1 ) ) )
More information about the CMF-checkins
mailing list