[CMF-checkins] CVS: CMF/CMFSetup - interfaces.py:1.10
registry.py:1.13 tool.py:1.14 toolset.py:NONE
Tres Seaver
tseaver at zope.com
Wed Jun 30 14:13:30 EDT 2004
Update of /cvs-repository/CMF/CMFSetup
In directory cvs.zope.org:/tmp/cvs-serv26029
Modified Files:
interfaces.py registry.py tool.py
Removed Files:
toolset.py
Log Message:
- The "toolset" handler had a bootstrapping problem; it relies on
state which is not kept anywhere in the site! Solve the problem
by making the handler a sub-object of the setup tool, and renaming
it "ToolsetRegistry" (note that its code migrated into the 'registry'
module).
- Add tests for export / import of toolset on actual site.
=== CMF/CMFSetup/interfaces.py 1.9 => 1.10 ===
--- CMF/CMFSetup/interfaces.py:1.9 Tue May 25 09:18:21 2004
+++ CMF/CMFSetup/interfaces.py Wed Jun 30 14:12:59 2004
@@ -256,6 +256,60 @@
the step is used, or default to ''.
"""
+class IToolsetRegistry( Interface ):
+
+ """ API for toolset registry.
+ """
+ def listForbiddenTools():
+
+ """ Return a list of IDs of tools which must be removed, if present.
+ """
+
+ def addForbiddenTool(tool_id ):
+
+ """ Add 'tool_id' to the list of forbidden tools.
+
+ o Raise KeyError if 'tool_id' is already in the list.
+
+ o Raise ValueError if 'tool_id' is in the "required" list.
+ """
+
+ def listRequiredTools():
+
+ """ Return a list of IDs of tools which must be present.
+ """
+
+ def getRequiredToolInfo( tool_id ):
+
+ """ Return a mapping describing a partiuclar required tool.
+
+ o Keys include:
+
+ 'id' -- the ID of the tool
+
+ 'class' -- a dotted path to its class
+
+ o Raise KeyError if 'tool_id' id not a known tool.
+ """
+
+ def listRequiredToolInfo():
+
+ """ Return a list of IDs of tools which must be present.
+ """
+
+ def addRequiredTool( tool_id, dotted_name ):
+
+ """ Add a tool to our "required" list.
+
+ o 'tool_id' is the tool's ID.
+
+ o 'dotted_name' is a dotted (importable) name of the tool's class.
+
+ o Raise KeyError if we have already registered a class for 'tool_id'.
+
+ o Raise ValueError if 'tool_id' is in the "forbidden" list.
+ """
+
class ISetupTool( Interface ):
""" API for SetupTool.
@@ -294,6 +348,11 @@
def getExportStepRegistry():
""" Return the IExportStepRegistry for the tool.
+ """
+
+ def getToolsetRegistry():
+
+ """ Return the IToolsetRegistry for the tool.
"""
def runImportStep( step_id, purge_old=True, run_dependencies=True ):
=== CMF/CMFSetup/registry.py 1.12 => 1.13 ===
--- CMF/CMFSetup/registry.py:1.12 Tue Jun 8 15:36:36 2004
+++ CMF/CMFSetup/registry.py Wed Jun 30 14:12:59 2004
@@ -13,6 +13,7 @@
from interfaces import IImportStepRegistry
from interfaces import IExportStepRegistry
+from interfaces import IToolsetRegistry
from permissions import ManagePortal
from utils import HandlerBase
from utils import _xmldir
@@ -393,6 +394,124 @@
InitializeClass( ExportStepRegistry )
+class ToolsetRegistry( Implicit ):
+
+ """ Track required / forbidden tools.
+ """
+ __implements__ = ( IToolsetRegistry, )
+
+ security = ClassSecurityInfo()
+ security.setDefaultAccess( 'allow' )
+
+ def __init__( self ):
+
+ self._clear()
+
+ #
+ # Toolset API
+ #
+ security.declareProtected( ManagePortal, 'listForbiddenTools' )
+ def listForbiddenTools( self ):
+
+ """ See IToolsetRegistry.
+ """
+ return tuple( self._forbidden )
+
+ security.declareProtected( ManagePortal, 'addForbiddenTool' )
+ def addForbiddenTool( self, tool_id ):
+
+ """ See IToolsetRegistry.
+ """
+ if tool_id in self._forbidden:
+ raise KeyError, 'Duplicate forbidden tool: %s' % tool_id
+
+ if self._required.get( tool_id ) is not None:
+ raise ValueError, 'Tool %s is required!' % tool_id
+
+ self._forbidden.append( tool_id )
+
+ security.declareProtected( ManagePortal, 'listRequiredTools' )
+ def listRequiredTools( self ):
+
+ """ See IToolsetRegistry.
+ """
+ return self._required.keys()
+
+ security.declareProtected( ManagePortal, 'getRequiredToolInfo' )
+ def getRequiredToolInfo( self, tool_id ):
+
+ """ See IToolsetRegistry.
+ """
+ return self._required[ tool_id ]
+
+ security.declareProtected( ManagePortal, 'listRequiredToolInfo' )
+ def listRequiredToolInfo( self ):
+
+ """ See IToolsetRegistry.
+ """
+ return [ self.getRequiredToolInfo( x )
+ for x in self._required.keys() ]
+
+ security.declareProtected( ManagePortal, 'addRequiredTool' )
+ def addRequiredTool( self, tool_id, dotted_name ):
+
+ """ See IToolsetRegistry.
+ """
+ if self._required.get( tool_id ) is not None:
+ raise KeyError, "Duplicate required tool: %s" % tool_id
+
+ if tool_id in self._forbidden:
+ raise ValueError, "Forbidden tool ID: %s" % tool_id
+
+ self._required[ tool_id ] = { 'id' : tool_id
+ , 'class' : dotted_name
+ }
+
+ security.declareProtected( ManagePortal, 'generateXML' )
+ def generateXML( self ):
+
+ """ Pseudo API.
+ """
+ return self._toolsetConfig()
+
+ security.declareProtected( ManagePortal, 'parseXML' )
+ def parseXML( self, text, encoding=None ):
+
+ """ Pseudo-API
+ """
+ reader = getattr( text, 'read', None )
+
+ if reader is not None:
+ text = reader()
+
+ parser = _ToolsetParser( encoding )
+ parseString( text, parser )
+
+ self._clear()
+
+ for tool_id in parser._forbidden:
+ self.addForbiddenTool( tool_id )
+
+ for tool_id, dotted_name in parser._required.items():
+ self.addRequiredTool( tool_id, dotted_name )
+
+ #
+ # Helper methods.
+ #
+ security.declarePrivate( '_clear' )
+ def _clear( self ):
+
+ self._forbidden = []
+ self._required = {}
+
+ security.declarePrivate( '_toolsetConfig' )
+ _toolsetConfig = PageTemplateFile( 'tscExport.xml'
+ , _xmldir
+ , __name__='toolsetConfig'
+ )
+
+InitializeClass( ToolsetRegistry )
+
class _ImportStepRegistryParser( HandlerBase ):
@@ -520,3 +639,40 @@
self._pending = None
InitializeClass( _ExportStepRegistryParser )
+
+
+class _ToolsetParser( HandlerBase ):
+
+ security = ClassSecurityInfo()
+ security.declareObjectPrivate()
+ security.setDefaultAccess( 'deny' )
+
+ def __init__( self, encoding ):
+
+ self._encoding = encoding
+ self._required = {}
+ self._forbidden = []
+
+ def startElement( self, name, attrs ):
+
+ if name == 'tool-setup':
+ pass
+
+ elif name == 'forbidden':
+
+ tool_id = self._extract( attrs, 'tool_id' )
+
+ if tool_id not in self._forbidden:
+ self._forbidden.append( tool_id )
+
+ elif name == 'required':
+
+ tool_id = self._extract( attrs, 'tool_id' )
+ dotted_name = self._extract( attrs, 'class' )
+ self._required[ tool_id ] = dotted_name
+
+ else:
+ raise ValueError, 'Unknown element %s' % name
+
+
+InitializeClass( _ToolsetParser )
=== CMF/CMFSetup/tool.py 1.13 => 1.14 ===
--- CMF/CMFSetup/tool.py:1.13 Tue Jun 8 15:36:36 2004
+++ CMF/CMFSetup/tool.py Wed Jun 30 14:12:59 2004
@@ -6,6 +6,7 @@
import time
from AccessControl import ClassSecurityInfo
+from Acquisition import aq_base
from Globals import InitializeClass
from OFS.Folder import Folder
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
@@ -20,10 +21,14 @@
from context import SnapshotExportContext
from registry import ImportStepRegistry
from registry import ExportStepRegistry
+from registry import ToolsetRegistry
from utils import _resolveDottedName
from utils import _wwwdir
+IMPORT_STEPS_XML = 'import_steps.xml'
+EXPORT_STEPS_XML = 'export_steps.xml'
+TOOLSET_XML = 'toolset.xml'
def exportStepRegistries( context ):
@@ -40,6 +45,57 @@
return 'Step registries exported'
+def importToolset( context ):
+
+ """ Import required / forbidden tools from XML file.
+ """
+ site = context.getSite()
+ encoding = context.getEncoding()
+ text = context.readDataFile( TOOLSET_XML )
+
+ setup_tool = getToolByName( site, 'portal_setup' )
+ toolset = setup_tool.getToolsetRegistry()
+
+ toolset.parseXML( text )
+
+ existing_ids = site.objectIds()
+ existing_values = site.objectValues()
+
+ for tool_id in toolset.listForbiddenTools():
+
+ if tool_id in existing_ids:
+ site._delObject( tool_id )
+
+ for info in toolset.listRequiredToolInfo():
+
+ tool_id = str( info[ 'id' ] )
+ tool_class = _resolveDottedName( info[ 'class' ] )
+
+ existing = getToolByName( site, tool_id, None )
+
+ if existing is None:
+ site._setObject( tool_id, tool_class() )
+
+ else:
+ unwrapped = aq_base( existing )
+ if not isinstance( unwrapped, tool_class ):
+ site._delObject( tool_id )
+ site._setObject( tool_id, tool_class() )
+
+ return 'Toolset imported'
+
+def exportToolset( context ):
+
+ """ Export required / forbidden tools to XML file.
+ """
+ site = context.getSite()
+ toolset = ToolsetRegistry().__of__( site )
+
+ xml = toolset.generateXML()
+ context.writeDataFile( TOOLSET_XML, xml, 'text/xml' )
+
+ return 'Toolset exported'
+
class SetupTool( UniqueObject, Folder ):
@@ -50,9 +106,6 @@
id = 'portal_setup'
meta_type = 'Portal Setup Tool'
- IMPORT_STEPS_XML = 'import_steps.xml'
- EXPORT_STEPS_XML = 'export_steps.xml'
-
_product_name = None
_profile_directory = None
_root_directory = None
@@ -67,6 +120,7 @@
, exportStepRegistries
, 'Export import / export steps.'
)
+ self._toolset_registry = ToolsetRegistry()
#
# ISetupTool API
@@ -116,6 +170,7 @@
self._updateImportStepsRegistry( encoding )
self._updateExportStepsRegistry( encoding )
+ self._updateToolsetRegistry( encoding )
security.declareProtected( ManagePortal, 'getImportStepRegistry' )
def getImportStepRegistry( self ):
@@ -130,6 +185,13 @@
""" See ISetupTool.
"""
return self._export_registry
+
+ security.declareProtected( ManagePortal, 'getToolsetRegistry' )
+ def getToolsetRegistry( self ):
+
+ """ See ISetupTool.
+ """
+ return self._toolset_registry
security.declareProtected( ManagePortal, 'executeStep' )
def runImportStep( self, step_id, run_dependencies=True, purge_old=True ):
@@ -427,7 +489,7 @@
"""
fq = self._getFullyQualifiedProfileDirectory()
- f = open( os.path.join( fq, self.IMPORT_STEPS_XML ), 'r' )
+ f = open( os.path.join( fq, IMPORT_STEPS_XML ), 'r' )
xml = f.read()
f.close()
@@ -458,7 +520,7 @@
"""
fq = self._getFullyQualifiedProfileDirectory()
- f = open( os.path.join( fq, self.EXPORT_STEPS_XML ), 'r' )
+ f = open( os.path.join( fq, EXPORT_STEPS_XML ), 'r' )
xml = f.read()
f.close()
@@ -477,6 +539,19 @@
, title=title
, description=description
)
+
+ security.declarePrivate( '_updateToolsetRegistry' )
+ def _updateToolsetRegistry( self, encoding ):
+
+ """ Update our toolset registry from our profile.
+ """
+ fq = self._getFullyQualifiedProfileDirectory()
+
+ f = open( os.path.join( fq, TOOLSET_XML ), 'r' )
+ xml = f.read()
+ f.close()
+
+ self._toolset_registry.parseXML( xml, encoding )
security.declarePrivate( '_doRunImportStep' )
def _doRunImportStep( self, step_id, context ):
=== Removed File CMF/CMFSetup/toolset.py ===
More information about the CMF-checkins
mailing list