[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} &#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