[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