Personal tools
You are here: Home Documentation Tutorials b-org: Creating content types the Plone 2.5 way Setup using GenericSetup
Support

Get Help

Join our chat rooms or support forums if you have more specific questions.

Plone Training
Learn how to design, build, and deploy a website in Plone through one of the numerous Plone training sessions around the world.
Find Plone training…
 
Document Actions

Setup using GenericSetup

b-org uses GenericSetup to impose itself on your Plone instance. Here's how it works.

Martin Aspeli

Plone 2.5 brings us closer to the promised land of Zope 3. Zope 3 brings us a new way of working. This tutorial will show how to marry the old and the new, to make Plone products that are more extensible, better tested and easier to maintain.
Page 9 of 15.

Hands up if you have ever written a workflow definition in Python and tried to figure out how to install it in your Extensions.py and thought, this is the least useful API I have ever had to deal with. Actually, the API is not that bad, it's just not very good for performing set-up. Similarly, it may start to make your separation-of-concerns-brainwashed mind a little uneasy that we tend to define aspects of the type's configuration as class attributes in an Archetypes class (though of course it's better than using a CMF FTI dict or mangling portal_types directly).

The fine folks who gave us the CMF came up with another way, called GenericSetup (after a few name changes - you may see the names CMFSetup and ContentSetup as well, which refer to predecessors of what is not GenericSetup). This is based on a declarative XML syntax that can represent site configuration. The configuration of an entire site is called a profile and can be imported and exported to replicate state across multiple Plone (or CMF) sites. There is a smaller version of a profile called an extension profile which can be used to extend a base profile. Both membrane and b-org use extension profiles to install themselves.

GenericSetup is described a tutorial by Rob Miller, cheif GenericSetup protagonist, so we won't repeat too much of the detail here. However, you should be aware that in Plone 2.5, GenericSetup has a slightly awkward user experience and does not have any well-defined way of performing uninstall, which stems from the fact that it was originally designed for the use case of taking a snapshot of the configuration of an entire site, not for installing and uninstalling products and extensions!

The other main shortcoming at the moment is that there is no way to specify interdependencies between profiles. It is important that membrane is installed before b-org, but if you're not careful it will happen the other way around. When you create a Plone site, you will be able to choose a number of extension profiles to apply (including meaningless ones like Archetypes - meaningless because Plone already invokes those when you set up a site). In this list, "Base organisation" comes before "membrane" by virtue of alphabetical sorting. Therefore, you can't just choose both and click "Add". Instead, you should select "membrane" first, and then add "Base organisation" via portal_setup, as described in the b-org README.txt:

  1. Go to portal_setup in the ZMI
  2. Click the Properties tab
  3. Select "Base organisation" as the active profile (since this is an extension profile, it won't override the base profile that set up your Plone site) and click Update.
  4. Go to the Import tab and click Import all steps at the bottom. Note that although it seems like this will re-install a whole bunch of stuff, it will only execute those steps that are actually listed in the import_steps.xml for the active profile, which in this case is b-org's.

If you didn't already set up membrane and you created a Plone site without the membrane extension profile, follow the same steps to install membrane before you install b-org.

So why did we do all this? Firt of all, both membrane and b-org are really infrastructure that fundamentally influence how you build your site, so the lack of uninstall isn't as bad as it would have been for more user-facing products. Secondly, with Plone 3.0, this will become easier, as the QuckInstaller (and hence the Add/Remove Products control panel page) becomes Extension Profile aware and gives some uninstall support.

At the end of this section, you will see how you can use a traditional QuickInstaller Install.py method and still get the nice XML syntax, with a bit of extra work.

Import steps

To GenericSetup, the installation of a third party product via an extension profile is considered to be the importing of that profile. A file import_steps.xml is used to determine which actual import steps will be executed. First, we need to tell GenericSetup where the import steps are defined, though, by registering the extension profile. This is done in the product's __init__.py:

from Products.CMFPlone.interfaces import IPloneSiteRoot
from Products.GenericSetup import EXTENSION, profile_registry

...

def initialize(context):
...
profile_registry.registerProfile('default',
'Base organisation',
'Organisation and project infrastructure',
'profiles/default',
'borg',
EXTENSION,
for_=IPloneSiteRoot)

This references the directory profiles/default, which contains various files:

import_steps.xml
Lists the steps to be performed during import (set-up)
export_steps.xml
Lists the steps to be performed during export - that is, if the configuration is changed in the ZODB and the site admin wishes to export the configuration to a file, these steps will be performed.
membrane_tool.xml
Configuration for membrane tools
skins.xml
Sets up skins in portal_types
types.xml
Configures FTIs (Factory Type Information settings) for the content types that b-org ships with. Each of the types listed here has a corresponding file in profiles/default/types (the name of the type and the name of the file should match). This file contains all the various FTI settings, such as friendly name, meta type, actions and aliases.
workflows.xml
Configures workflows. This works in the same way as types.xml - the main file configures the names of the workflows and the bindings of workflows to content types. The actual workflow definitions, including states and transitions, are found in profiles/default/workflows.
The import_steps.xml which orchistrates all this looks like follows:

<?xml version="1.0"?>
<import-steps>
<import-step id="borg_various" version="20060803-01"
handler="Products.borg.setuphandlers.importVarious"
title="Various base-org Settings">
<dependency step="typeinfo"/>
<dependency step="skins"/>
<dependency step="workflow"/>
</import-step>
</import-steps>
Note that we don't actually specify most of the files - they are referenced by the base profile that was used to set up Plone or the extension profile for membrane. GenericSetup knows all the registered profiles' steps, and looks for the corresponding files.

Various setup handlers

The one setup handler you do see is the "various" handler. This is dependent on the set-up of type info, skins and workflow. Ordinarily, setup handlers will utilise GenericSetup base classes, adapters and utility functions to parse XML files. However, it's not always convenient to invent a generic XML syntax for all types of configuration. The importVarious pattern is used by many products that need to perform some custom set-up in Python. It is invoked as if it were a handler for an XML file, but it just happens to have different side-effects. The main caveat with this type of set-up, of course, is that it cannot symmetrically export (and then re-import) the configuration, and it is more difficult to re-use.

importVarious looks as follows:

from StringIO import StringIO

...

def setupPlugins(portal, out):
"""Install and prioritize the project local-role PAS plug-in.
"""

...

def setupPortalFactory(portal, out):
"""Add borg types to portal_factory
"""

...

def addProjectPlacefulWorkflowPolicy(portal, out):
"""Add the placeful workflow policy used by project spaces.
"""

....

def importVarious(context):
"""
Import various settings.

Provisional handler that does initialization that is not yet taken
care of by other handlers.
"""
site = context.getSite()
out = StringIO()

setupPlugins(site, out)
setupPortalFactory(site, out)
addProjectPlacefulWorkflowPolicy(site, out)

logger = context.getLogger("borg")
logger.info(out.getvalue())

We set up the PAS plugins, register our types with portal_factory and add a placeful workflow policy. The exact code to perform each of these steps is not listed here to save space, but they use the same techniques you would use in an Install.py file. Note that the portal_factory setup is available in a more friendly XML format in Plone 2.5.1 and later, which was released after b-org.

GenericSetup without portal_setup

When Plone 3.0 arrives, it will make the Add/Remove Products control panel aware of extension profiles, and thus provide a more user friendly way of performing install using GenericSetup. It will also support uninstall. Until that time, however, it is possible to re-use the GenericSetup XML handlers to parse files like types.xml  and workflow.xml from a regular Install.py installation. We do this in the charity example.

When importing, GenericSetup requires a setup environment, and usually an object to work on. A simple SetupEnviron is found in charity/Extensions/utils.py, along with a method called updateFTI() which can take an FTI object and update its settings based on a types.xml-like file. This method takes a module and the id of an FTI to update, and finds the corresponding file.

It is used in charity/Extensions/Install.py as follows:
from Products import charity

from Products.charity.Extensions.utils import updateFTI

def install(self, reinstall=False):

...

if not reinstall:
updateFTI(self, charity, 'Department')
updateFTI(self, charity, 'Employee')
updateFTI(self, charity, 'Project')

The relevant files may be found in charity/Extensions/setup/types/.
 
by Martin Aspeli last modified November 7, 2006 - 05:11 All content is copyright Plone Foundation and the individual contributors.

For any issues with the web site functionality, please file a ticket.

Please consult the policy on plone.org content if you want your content published on this site.

Servers and hosting by