Creating an uninstall profile

by Rob Miller last modified Feb 04, 2009 02:34 AM

GenericSetup allows you to remove configuration

So far you have learned how to add configuration to a Plone site with GenericSetup... But what if you want to remove it again? Typically any Plone Product author wants to offer uninstall of his project.
Fortunately, GenericSetup allows you to pinpoint and remove selected elements. From a high level you do this:

  • Create an additional GenericSetup profile with the name "uninstall" - many times you can just copy the "default" profile
  • Sprinkle remove="True" attributes around the XML files
  • Wire the uninstall profile up with the Install.py of your product if you like.

How to create an uninstall profile

Consider a profile that configures a custom portal type, e.g. the following lines in types.xml and the corresponding MyType.xml
<?xml version="1.0"?>
<object name="portal_types" meta_type="Plone Types Tool">
<object name="MyType"
meta_type="Factory-based Type Information with dynamic views"/>
</object>
Now, copy the types.xml over to a new profile directory called uninstall and alter it a bit:
<?xml version="1.0"?>
<object name="portal_types" meta_type="Plone Types Tool">
<object name="MyType"
meta_type="Factory-based Type Information with dynamic views" remove="True" />
</object>
That's it. Run the new profile and it will remove the MyType configuration.

If you like, you can clean it up a bit:
<?xml version="1.0"?>
<object name="portal_types">
<object name="MyType" remove="True"/>
</object>

What works and what doesn't yet

The magic "remove" attribute has been implemented for many of the GenericSetup handlers, but not all of them.

Remove works for these handlers:
  • Skins
  • Types
  • Workflows
  • Catalog indexes

It does not work for these -- yet:
  • Actions
  • Properties
  • Configlets

I haven't tested with the rest of the handlers.


Wiring up the Quick Installer

You can wire up the uninstall profile with Quick Installer the same way as you wire up a normal install profile, e.g.
from Products.CMFCore.utils import getToolByName

def uninstall(portal):
setup_tool = getToolByName(portal, 'portal_setup')
setup_tool.setImportContext('profile-MYPRODUCT:uninstall')
setup_tool.runAllImportSteps()
setup_tool.setImportContext('profile-CMFPlone:plone')
return "Ran all uninstall steps."
Until all the GenericSetup handlers support the "remove" attribute, you might need a hybrid uninstall method that runs an uninstall profile and uninstalls the remaining elements using old style scripting afterwards.