[Checkins] SVN: GenericSetup/branches/rafrombrc_cps_upgrade_integration/ * first integration of CPS upgrade code... need tests!

Rob Miller ra at burningman.com
Fri Mar 16 17:53:29 EDT 2007


Log message for revision 73255:
  * first integration of CPS upgrade code... need tests!
  

Changed:
  U   GenericSetup/branches/rafrombrc_cps_upgrade_integration/meta.zcml
  U   GenericSetup/branches/rafrombrc_cps_upgrade_integration/tool.py
  A   GenericSetup/branches/rafrombrc_cps_upgrade_integration/upgrade.py
  A   GenericSetup/branches/rafrombrc_cps_upgrade_integration/www/setup_upgrades.zpt
  U   GenericSetup/branches/rafrombrc_cps_upgrade_integration/zcml.py

-=-
Modified: GenericSetup/branches/rafrombrc_cps_upgrade_integration/meta.zcml
===================================================================
--- GenericSetup/branches/rafrombrc_cps_upgrade_integration/meta.zcml	2007-03-16 21:30:15 UTC (rev 73254)
+++ GenericSetup/branches/rafrombrc_cps_upgrade_integration/meta.zcml	2007-03-16 21:53:29 UTC (rev 73255)
@@ -2,11 +2,20 @@
     xmlns="http://namespaces.zope.org/zope"
     xmlns:meta="http://namespaces.zope.org/meta">
 
-  <meta:directive
-      name="registerProfile"
-      namespace="http://namespaces.zope.org/genericsetup"
-      schema=".zcml.IRegisterProfileDirective"
-      handler=".zcml.registerProfile"
-      />
+  <meta:directives namespace="http://namespaces.zope.org/genericsetup">
 
+    <meta:directive
+       name="registerProfile"
+       schema=".zcml.IRegisterProfileDirective"
+       handler=".zcml.registerProfile"
+       />
+
+    <meta:directive
+       name="upgradeStep"
+       schema=".zcml.IUpgradeStepDirective"
+       handler=".zcml.upgradeStep"
+       />
+
+  </meta:directives>
+
 </configure>

Modified: GenericSetup/branches/rafrombrc_cps_upgrade_integration/tool.py
===================================================================
--- GenericSetup/branches/rafrombrc_cps_upgrade_integration/tool.py	2007-03-16 21:30:15 UTC (rev 73254)
+++ GenericSetup/branches/rafrombrc_cps_upgrade_integration/tool.py	2007-03-16 21:53:29 UTC (rev 73255)
@@ -28,6 +28,9 @@
 from zope.interface import implements
 from zope.interface import implementedBy
 
+from Products.CMFCore.utils import getToolByName
+from Products.GenericSetup import BASE
+
 from interfaces import EXTENSION
 from interfaces import ISetupTool
 from interfaces import SKIPPED_FILES
@@ -43,6 +46,8 @@
 from registry import ToolsetRegistry
 from registry import _profile_registry
 
+from upgrade import listUpgradeSteps
+
 from utils import _resolveDottedName
 from utils import _wwwdir
 
@@ -163,7 +168,7 @@
 
         """ See ISetupTool.
         """
-        return 'ascii'
+        return 'utf-8'
 
     security.declareProtected(ManagePortal, 'getImportContextID')
     def getImportContextID(self):
@@ -370,6 +375,9 @@
                        {'label' : 'Export',
                         'action' : 'manage_exportSteps'
                        },
+                       {'label' : 'Upgrades',
+                        'action' : 'manage_upgrades'
+                        },
                        {'label' : 'Snapshots',
                         'action' : 'manage_snapshots'
                        },
@@ -491,6 +499,9 @@
                            'attachment; filename=%s' % result['filename'])
         return result['tarball']
 
+    security.declareProtected(ManagePortal, 'manage_upgrades')
+    manage_upgrades = PageTemplateFile('setup_upgrades', _wwwdir)
+
     security.declareProtected(ManagePortal, 'manage_snapshots')
     manage_snapshots = PageTemplateFile('sutSnapshots', _wwwdir)
 
@@ -524,6 +535,7 @@
     def listProfileInfo(self):
 
         """ Return a list of mappings describing registered profiles.
+        Base profile is listed first, extensions are sorted.
 
         o Keys include:
 
@@ -537,8 +549,17 @@
 
           'product' -- name of the registering product
         """
-        return _profile_registry.listProfileInfo()
+        base = []
+        ext = []
+        for info in _profile_registry.listProfileInfo():
+            if info.get('type', BASE) == BASE:
+                base.append(info)
+            else:
+                ext.append(info)
+        ext.sort(lambda x, y: cmp(x['id'], y['id']))
+        return base + ext
 
+
     security.declareProtected(ManagePortal, 'listContextInfos')
     def listContextInfos(self):
 
@@ -609,7 +630,34 @@
                                           ignore_blanks,
                                          )
 
+    #
+    # Upgrades management
+    #
+    security.declarePrivate('_getCurrentVersion')
+    def _getCurrentVersion(self):
+        # XXX this should return the current version of the
+        # appropriate profile.. need to define what this means
+        return None
 
+    security.declareProtected(ManagePortal, 'listUpgrades')
+    def listUpgrades(self, show_old=False):
+        """Get the list of available upgrades.
+        """
+        portal = getToolByName(self, 'portal_url').getPortalObject()
+        if show_old:
+            source = None
+        else:
+            source = self._getCurrentVersion()
+        upgrades = listUpgradeSteps(portal, source)
+        res = []
+        for info in upgrades:
+            info = info.copy()
+            info['haspath'] = info['source'] and info['dest']
+            info['ssource'] = '.'.join(info['source'] or ('all',))
+            info['sdest'] = '.'.join(info['dest'] or ('all',))
+            res.append(info)
+        return res
+
     #
     #   Helper methods
     #

Added: GenericSetup/branches/rafrombrc_cps_upgrade_integration/upgrade.py
===================================================================
--- GenericSetup/branches/rafrombrc_cps_upgrade_integration/upgrade.py	2007-03-16 21:30:15 UTC (rev 73254)
+++ GenericSetup/branches/rafrombrc_cps_upgrade_integration/upgrade.py	2007-03-16 21:53:29 UTC (rev 73255)
@@ -0,0 +1,82 @@
+##############################################################################
+#
+# Copyright (c) 2005 Nuxeo SARL <http://nuxeo.com>
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+_upgrade_registry = {} # id -> step
+
+class UpgradeStep(object):
+    """A step to upgrade a component.
+    """
+    def __init__(self, title, profile, source, dest, handler,
+                 checker=None, sortkey=0):
+        self.id = str(abs(hash('%s%s%s%s' % (title, source, dest, sortkey))))
+        self.title = title
+        if source == '*':
+            source = None
+        elif isinstance(source, basestring):
+            source = tuple(source.split('.'))
+        self.source = source
+        if dest == '*':
+            dest = None
+        elif isinstance(dest, basestring):
+            dest = tuple(dest.split('.'))
+        self.dest = dest
+        self.handler = handler
+        self.checker = checker
+        self.sortkey = sortkey
+        self.profile = profile
+
+    def versionMatch(self, portal, source):
+        return (source is None or
+                self.source is None or
+                source <= self.source)
+
+    def isProposed(self, portal, source):
+        """Check if a step can be applied.
+
+        False means already applied or does not apply.
+        True means can be applied.
+        """
+        checker = self.checker
+        if checker is None:
+            return self.versionMatch(portal, source)
+        else:
+            return checker(portal)
+
+    def doStep(self, portal):
+        self.handler(portal)
+
+def _registerUpgradeStep(step):
+    _upgrade_registry[step.id] = step
+
+def listUpgradeSteps(portal, source):
+    """Lists upgrade steps available from a given version.
+    """
+    res = []
+    for id, step in _upgrade_registry.items():
+        proposed = step.isProposed(portal, source)
+        if (not proposed
+            and source is not None
+            and (step.source is None or source > step.source)):
+            continue
+        info = {
+            'id': id,
+            'step': step,
+            'title': step.title,
+            'source': step.source,
+            'dest': step.dest,
+            'proposed': proposed,
+            }
+        res.append(((step.source or '', step.sortkey, proposed), info))
+    res.sort()
+    res = [i[1] for i in res]
+    return res

Added: GenericSetup/branches/rafrombrc_cps_upgrade_integration/www/setup_upgrades.zpt
===================================================================
--- GenericSetup/branches/rafrombrc_cps_upgrade_integration/www/setup_upgrades.zpt	2007-03-16 21:30:15 UTC (rev 73254)
+++ GenericSetup/branches/rafrombrc_cps_upgrade_integration/www/setup_upgrades.zpt	2007-03-16 21:53:29 UTC (rev 73255)
@@ -0,0 +1,69 @@
+<h1 tal:replace="structure context/manage_page_header">PAGE HEADER</h1>
+<h2 tal:replace="structure context/manage_tabs">TABS</h2>
+
+<h3>Upgrades</h3>
+
+<p class="form-help">
+  The portal is currently upgraded to version
+  <strong tal:define="portal context/portal_url/getPortalObject"
+          tal:content="python:portal.getProperty('last_upgraded_version')
+                              or 'unknown'">
+    VERSION
+  </strong>.
+</p>
+
+<tal:block define="show_old request/show_old | python:0;
+                   upgrades python:context.listUpgrades(show_old=show_old)">
+
+<form method="post" action="manage_doUpgrades" tal:condition="upgrades">
+<p class="form-help">
+  Available upgrades:
+</p>
+<input type="hidden" name="show_old:int" value="VALUE"
+       tal:attributes="value show_old" />
+<table>
+  <tr valign="top" tal:repeat="info upgrades">
+    <td>
+      <input type="checkbox" name="upgrades:list"
+             value="VALUE" checked="CHECKED"
+             tal:attributes="value info/id;
+                             checked python:info['proposed'] and not show_old;
+                             "/>
+    </td>
+    <td>
+      <div tal:replace="info/title">INFO</div>
+    </td>
+    <td class="form-help">
+      <div tal:condition="info/haspath"
+           tal:content="structure string:(${info/ssource} &amp;#8594; ${info/sdest})">PATH</div>
+    </td>
+    <td class="form-help">
+      <div tal:condition="not:info/proposed"
+           tal:replace="default">(done)</div>
+    </td>
+  </tr>
+
+  <tr valign="top">
+    <td colspan="4">
+      <input class="form-element" type="submit" value="Upgrade" />
+    </td>
+  </tr>
+</table>
+</form>
+
+<p tal:condition="not:upgrades">
+  No upgrade available.
+</p>
+
+<form method="post" action="manage_upgrades" tal:condition="not:show_old">
+<p class="form-help">
+  Show old upgrades:
+  <input type="submit" value="Show" />
+  <input type="hidden" name="show_old:int" value="1" />
+</p>
+</form>
+
+
+</tal:block>
+
+<h1 tal:replace="structure context/manage_page_footer">PAGE FOOTER</h1>

Modified: GenericSetup/branches/rafrombrc_cps_upgrade_integration/zcml.py
===================================================================
--- GenericSetup/branches/rafrombrc_cps_upgrade_integration/zcml.py	2007-03-16 21:30:15 UTC (rev 73254)
+++ GenericSetup/branches/rafrombrc_cps_upgrade_integration/zcml.py	2007-03-16 21:53:29 UTC (rev 73255)
@@ -25,6 +25,8 @@
 from registry import _profile_registry
 
 
+#### genericsetup:registerProfile
+
 class IRegisterProfileDirective(Interface):
 
     """Register profiles with the global registry.
@@ -81,6 +83,56 @@
         )
 
 
+#### genericsetup:upgradeStep
+
+import zope.schema
+from upgrade import UpgradeStep
+from upgrade import _registerUpgradeStep
+
+class IUpgradeStepDirective(Interface):
+    """Register an upgrade setup.
+    """
+    title = zope.schema.TextLine(
+        title=u"Title",
+        required=True)
+
+    source = zope.schema.ASCII(
+        title=u"Source version",
+        required=False)
+
+    destination = zope.schema.ASCII(
+        title=u"Destination version",
+        required=False)
+
+    sortkey = zope.schema.Int(
+        title=u"Sort key",
+        required=False)
+
+    profile = zope.schema.TextLine(
+        title=u"GenericSetup profile id",
+        required=True)
+
+    handler = GlobalObject(
+        title=u"Upgrade handler",
+        required=True)
+
+    checker = GlobalObject(
+        title=u"Upgrade checker",
+        required=False)
+
+def upgradeStep(_context, title, profile, handler, source='*', destination='*',
+                sortkey=0, checker=None):
+    step = UpgradeStep(title, profile, source, destination, handler, checker,
+                       sortkey)
+    _context.action(
+        discriminator = ('upgradeStep', source, destination, handler, sortkey),
+        callable = _registerUpgradeStep,
+        args = (step,),
+        )
+
+
+#### cleanup
+
 def cleanUp():
     global _profile_regs
     for profile_id in _profile_regs:



More information about the Checkins mailing list