Another milestone on the road to Zen with Ingeniweb components
Latest version : 2.1.2

PloneInstallation

> A collection of helper scripts for Plone product installation <

About PloneInstallation

A collection of helper scripts for Plone product installation

PloneInstallation has been designed by the INGENIWEB team.

PloneInstallation 2.1.2 is licensed under the GNU GPL license.

Do you like this product? You can support its authors by clicking the button below:
Support This Project

Screenshots

makes no sense

Readme

PloneInstallation

Version 0.2 (CVS HEAD/Unreleased)

This package doesn't add any functionality to Plone. It just provides friendly resources to make Plone adds (un)installation scripts easier.

Requirements

o Zope 2.6.2 (+)

o Plone 2.x (complete package with all tools)

o DCWorkflowDump - (optional) if you need to use the WorkflowInstaller

o Archetypes 1.3.x (optional) if you need to use the ATTypesInstaller

The Big Picture

All Plone extensions developers need to write (un)installation scripts to create new Plone resources. Those kind of scripts are somehow repetitive and annoying to write and test, when doing approximately the same things: register a type, add a layer to a skin...

This product provides resources to make your (un)installation scripts easy to create in a dozen of minutes.

You will find here classes that handle (un)installation and (un)registration of your Plone extensions:

o Skin layer (un)installation

o Skin (un)registration

o Portal types (un)registration

o Archetypes portal types (un)registration

o Plone tool (un)installation

o Catalog indexes and metadata (un)installation

o Workflow (un)installation (requires DCWorkflowDump)

o Portlets/Slots (un)registration

o Changing properties from the Plone standard property sheets

o Property sheets (un)installation

o Configlets (un)registration

o Actions (un)registration

o Zexp files (un) importing

o External methods (un)installation

o Run External methods easyly at install and/or uninstall time

o New role with permissions (un)installation in security matrix

InstallationContext class

An 'InstallationContext' object just provides some resources passed to the various installers. Your installation scripts must start with the creation of a new InstallationContext.

The constructor of InstallationContext object :

  • '__init__(self, context, product_globals, verbose_report=True)' : where 'context' is the portal itself ('self' passed to the 'install' and 'uninstall' functions by the portal_quickinstaller.

Its public resource provides the attributes

  • 'portal' : If you don't know what it is, you should stop reading this and play with something else :-)
  • 'portal_actions', 'portal_catalog', 'portal_controlpanel', 'portal_properties', 'portal_quickinstaller', 'portal_skins', 'portal_types', 'portal_url', 'portal_workflow' : misc tools of a standard Plone.
  • 'report' : a StringIO stream you can use to add your own messages passed to the Quickinstaller.
  • 'product_globals' : The 'globals()' of your product passed to the constructor.
  • 'productName()' : The name of your product is computed for you.
  • 'requiresProduct(productname)' : Checks wether a product is available in your Zope instance. Raises an 'InstallationError' if not.
  • 'requiresInstalledProduct(productname)' : Checks wether a products is available in your Zope instance and installed in your Plone site. Raises an 'InstallationError' if not.
  • 'logInfo(message)', 'logWarning(message)', 'logError(message)' : Some logging utilities. Logged messages are available in the portal_quickinstaller. Using 'logError' from an xxInstaller method stops the (un)installation and a full transaction rollback.

InstallationRunner class

An InstallationRunner provides a registry for your custom xxInstaller objects. All installers objects you need for your project must be registered in an InstallationRunner object, and you must use the same InstallationRunner object at install and uninstall time. The below example shows an easy example to do this.

Its public methods are :

  • '__init__(self, installers)' : Register some installers installer objects **must* subclass 'InstallerBase'

  • 'addInstallers(installers)' : Register additional installers installer objects **must* subclass 'InstallerBase'

  • 'install(context, auto_reorder=False, autoReorder=False)' : Processes the installation of registered installers. 'context' is the InstallationContext object used. You may let the InstallationRunner object reorder automatically the registered installers in a safe way passing 'auto_reorder=True' or 'autoReorder=True' (backward compatibility)

  • 'uninstall(context, auto_reorder=False, autoReorder=False)' :

    Processes uninstallation based on all xxInstaller objects. The signature of 'uninstall' is identical to the one of 'install' above. Note that uninstalling processes the various installers in reverse order.

Installer classes

ActionsInstaller

An ActionsInstaller adds actions to any action provider object in your Plone instance. Of course if no specific action provider is specified, the actions will be added to the classical 'portal_actions' .

Constructor signature:

  • ' __init__(self, actions, actions_provider="portal_actions", **kw)'

    System Message: WARNING/2 (<string>, line 148); backlink

    Inline strong start-string without end-string.

    • 'actions' : a sequence of action defintions, each one being a mapping with keys:

      o * 'id' : string

      o * 'name' : string

      o * 'action' : TAL expression as string

      o 'condition' : TAL expression as string (default empty string)

      o 'permission' : string or imported permission (default: 'View')

      o * 'category' : string,

      o 'visible' : 1 or 0 (default: 1)

      keys starting with * are mandatory

      See class Products.CMFCore.ActionProviderBase.ActionProviderBase for more infos.

    • 'actions_provider' : the id of a Plone action provider tool

    • 'kw' : override defaults like 'stop_on_error' attribute

ATTypesInstaller

You should use the ATTypesInstaller if you want to make your AT based content types available to your users. The ATTypesInstaller does much more : you may provide a list of portal_types you want to hide as well as a list of replacement types.

Of course, the uninstallation (tries to) undo all that until you didn't mess manually in the portal_types :-)

Constructor signature:

  • '__init__(self, package_name=None, excluded_types=(), project_types_map=[], **kw)'

    System Message: WARNING/2 (<string>, line 187); backlink

    Inline strong start-string without end-string.

    • 'package_name' : the target AT package name (default: the current package)

    • 'exclused_types' : a sequence of portal_types to be removes (from addables)

    • 'project_types_map' : a sequence of tuples for renaming portal_types in the form:

      [(old_portal_type, new_portal_type), ...]

    • 'kw': override defaults like 'stop_on_error's attribute

CatalogInstaller

A CatalogInstaller helps you to add new indexes and metadata to the portal catalog. Warning, complex indexes like TextIndexNG2 or TopicIndex are not supported (yet).

Constructor signature:

  • ' __init__(self, indexes, metadata=(), **kw)'

    System Message: WARNING/2 (<string>, line 206); backlink

    Inline strong start-string without end-string.

    • 'indexes' : sequence of (id, type, extra) that define new indexes.
    • 'metadata' : (sequence of) metadata to be added kw: override defaults like 'stop_on_error' attribute.
    • 'kw' : override defaults like 'stop_on_error' attribute

ConfigletsInstaller

A ConfigletInstaller plugs an entry in the plone configuration panel.

Constructor signature:

  • '__init__(self, configlets, **kw)'

    System Message: WARNING/2 (<string>, line 223); backlink

    Inline strong start-string without end-string.

    • 'configlet' : (sequence of) mappings with keys:

      o 'id' : the id of the configlet

      o * 'name' : a label for your configlet

      o * action: TALES expression

      o 'condition' : TALES expression (default: empty expression)

      o 'permission' : defaults to ManagePortal

      o 'category' : defaults to 'Products'

      o 'visible' : default is 1 (visible)

      o 'appId' : defaults is the product's name

      o 'imageUrl' : defaults to None (no image)

      o 'description' : defaults to empty string

      keys starting with '*' are mandatory

    • 'kw' : override defaults like 'stop_on_error' attribute

ExternalMethodInstaller

An ExternalMethodInstaller controls the (un)installation of an External method in your portal or elsewhere.

Constructor signature:

  • '__init__(self,module, function, path, title="", roles=(), force=False, **kw)'

    System Message: WARNING/2 (<string>, line 258); backlink

    Inline strong start-string without end-string.

    • 'module' : the name of the module as in ZMI. i.e. 'MyProduct.StuffModule'
    • 'function' : the name of the function as in ZMI
    • 'path' : the name or path to the External method, including its id. If the path starts with '/' like '/foo/bar', this is an absolute path from Zope root. In any other case, like 'foo/bar', this is a relative path from the portal. In most cases, you will need to provide only the id of that external method.
    • 'title' : the title for that external method
    • 'roles' : the list of roles that may execute the external method. By default, anonymous may run such external methods.
    • 'force' : delete any object at the path of the future external method (if any)

ExternalMethodRunner

Executes some external methods at install and/or uninstall time in the context of the Plone Portal.

Constructor signature:

  • '__init__(self, ext_install=(), ext_uninstall=(), **kw)'

    System Message: WARNING/2 (<string>, line 284); backlink

    Inline strong start-string without end-string.

    • 'ext_install' : tuple or tuple of tuples as ('module', 'function') executed at install time
    • 'ext_uninstall' : tuple or tuple of tuples as ('module', 'function') executes at uninstall time
    • 'kw' : override defaults like stop_on_error attribute

PortletsInstaller

A PortletInstaller controls the (un)installation of global portlets on your portal.

Constructor signature:

  • '__init__(self, portlet_path, slot_prop_name="left_slots", **kw)'

    System Message: WARNING/2 (<string>, line 300); backlink

    Inline strong start-string without end-string.

    • 'portlet_path' : (sequence of) path expression(s) to the portlet macro(s).
    • 'slot_prop_name' : name of the slots property
    • 'kw' : override defaults like 'stop_on_error' attribute

PropertysheetInstaller

A PropertysheetInstaller will (un)install a property sheet in portal_properties.

Constructor signature:

  • '__init__(self, sheet_name, properties, **kw)'

    System Message: WARNING/2 (<string>, line 314); backlink

    Inline strong start-string without end-string.

    • 'sheet_name' : the name as appearing in portal_properties
    • 'properties' : a sequence of (id, value, type) tuples as expected by manage_addProperty
    • 'kw' : override defaults like 'stop_on_error' attribute

RoleInstaller

A RoleInstaller will (un)install a new role in the security matrix of the portal.

Costructor signature:

  • '__init__(self, role, model='Anonymous', allowed=(), denied=(), **kw)'

    System Message: WARNING/2 (<string>, line 329); backlink

    Inline strong start-string without end-string.

    • 'role' : name of the new role
    • 'model' : new role has the same permissions granted as 'model' role
    • 'allowed' : (sequence of) allowed permission(s)
    • 'denied' : (sequence of) denied permission(s)
    • 'kw' : override defaults like stop_on_error attribute

SkinInstaller

A SkinInstaller makes a new skin for you in a couple of lines.

Constructor signature:

  • '__init__(self, skin_name, layers_dir="skins", new_layers=(), is_default=0, **kw)'

    System Message: WARNING/2 (<string>, line 347); backlink

    Inline strong start-string without end-string.

    • 'skin_name' : skin name to be installed.
    • 'layers_dir' : subdirectory of the Product that contains the layers.
    • 'new_layers' : odered sequence of layers to push before 'custom'
    • 'is_default' : set this skin as default skin
    • 'kw' : override defaults like 'stop_on_error' attribute

SkinLayersInstaller

A SkinLayersInstaller sets new layers in your portal_skins. Warning : thos installer doesn't install a new skin as the SkinInstaller does.

Constructor signature:

  • ' __init__(self, layers_dir="skins", marker="custom", **kw)'

    System Message: WARNING/2 (<string>, line 367); backlink

    Inline strong start-string without end-string.

    • 'layers_dir' : subdirectory of the Product that contains the layers
    • 'marker' : the name of the (preferably) standard layer after which the new layer(s) are inserted
    • 'kw' : override defaults like 'stop_on_error' attribute

StandardPropertiesInstaller

Change the values of the standard property sheets.

Constructor signature:

  • ' __init__(self, sheetName, properties, **kw)'

    System Message: WARNING/2 (<string>, line 381); backlink

    Inline strong start-string without end-string.

    • 'sheetName': the name as appearing in portal_properties

    • 'properties': a sequence of (id, value) tuples as expected by

      manage_changeProperties

    • 'kw': override defaults like 'stop_on_error' attribute

ToolInstaller

Installs a tool in the portal. Note that your tool must anyway be registered in Zope/CMF/Plone as usual in your product's '__init__.py'.

Constructor signature:

  • ' __init__(self, tool_class, **kw)'

    System Message: WARNING/2 (<string>, line 398); backlink

    Inline strong start-string without end-string.

    • 'tool_class' : class definition of the tool. Assumes that class provides 'title' and 'meta_type' attributes.
    • 'kw' : override defaults like 'stop_on_error' attribute

TypeInstaller

You should choose a TypeInstaller to install new content types that have been built "the old way" (without Archetypes).

Constructor signature:

  • '__init__(self, fti, **kw)'

    System Message: WARNING/2 (<string>, line 412); backlink

    Inline strong start-string without end-string.

    • 'fti' : a (sequence of) usual factory type information structure(s)
    • 'kw' : override defaults like 'stop_on_error' attribute

WorkflowInstaller

A WorkflowInstaller sets a new workflow you made and exported with DCWorkflowDump.

You can get DCWorkflowDump from http://www.sourceforge.net/collective

Constructor signature:

  • '__init__(self, workflow_name, portal_types, **kw)'

    System Message: WARNING/2 (<string>, line 427); backlink

    Inline strong start-string without end-string.

    • 'workflow_name' : The name of your workflow file built by DCWorkflowDump (without the ".py"). This file must be in the same folder as your Install.py (typically in the "Extensions" folder of your product)
    • 'portal_types' : (sequence of) portal types (names) associated with this workflow
    • 'kw' : override defaults like 'stop_on_error' attribute or pass 'defaultWorkflow=True' if you want to make this workflow the default workflow.

ZexpInstaller

A ZexpInstaller installs objects from a standard Zope export format (.zexp) file. This may be an alternate way to install workflows.

Constructor signature:

  • '__init__(self, zexp_filename, path, set_owner=True, **kw)'

    System Message: WARNING/2 (<string>, line 449); backlink

    Inline strong start-string without end-string.

    • 'zexp_filename' : the file must be located in the Prooduct's Extensions folder
    • 'path' : the path of the object in which the import is processed. The path is evaluated using "restrictedTraverse" from the portal object. Use an empty string to import into the portal itself.
    • 'set_owner' : set the ownership of imported object(s) otherwise, keeps the ownership.
    • 'kw' : override defaults like 'stop_on_error' attribute

Sample

Sample of use of this package, you may perhaps never need such a complex installation but this shows all possible xxInstaller classes

#
# #   ******************************
# #   ** Sample Install.py module **
# #   ******************************
# # Global installation resources
# from Products.PloneInstallation.public import *
#
# # Product specific resources
# from Products.DummyInstall import product_globals
# from Products.DummyInstall.DummyTool import DummyTool
# from Products.DummyInstall.DummyType import factory_type_information2
#
# def getRunners():
#     return InstallationRunner(
#
#         # 3 new indexes and 2 metadata for portal_catalog
#         CatalogInstaller(
#             (('stuff', 'FieldIndex', None),
#              ('foo', 'DateIndex', None),
#              ('bar', 'KeywordIndex', None)),
#             metadata = ('stuff', 'bar')),
#
#         # Change these properties from standard propertysheet
#         StandardPropertiesInstaller(
#             'navtree_properties',
#             (('batchSize', 40),
#              ('idsNotToList', ['secret', 'confidential']))),
#
#         # Add new propertysheet and some properties in it
#         PropertysheetInstaller(
#             'my_propertysheet',
#             (('title', 'A test propertysheet', 'string'),
#              ('somevalue', 100, 'int'),
#              ('othervalue', 'Yeah', 'string'))),
#
#         # Add a portlet in left slots
#         PortletInstaller('here/myprotlet1/macros/portlet'),
#
#         # Add a portlet in right slots
#         PortletInstaller('here/myprotlet1/macros/portlet',
#                          slot_prop_name='right_slots'),
#
#         # Add a new forkflow for Topic and Document types
#         WorkflowInstaller('my_workflow',
#                           ('Document', 'Topic')),
#
#         # Add a couple of actions
#         ActionsInstaller(({'id': 'someAction',
#                            'name': 'someActionName',
#                            'action': 'string:${portal_url}/toto',
#                            'category': 'object',
#                            'visible': 1},
#                           {'id': 'otherAction',
#                            'name': 'otherActionName',
#                            'action': 'string:${portal_url}/toto',
#                            'condition': 'python:user.isAnonymous()',
#                            'permission': 'View',
#                            'category': 'object',
#                            'visible': 1})),
#
#         # Create a new default skin
#         SkinInstaller('Maturity',
#                       new_layers=('custom', 'epoz', 'gruf'),
#                       is_default=1),
#
#         # Add functionality to Plone config
#         ConfigletsInstaller({'id': 'dummyConfig',
#                              'name': 'Dummy stuff configuration',
#                              'action': "string:${portal_url}/prefs_install_products_form"}),
#
#
#         # Add a new tool
#         ToolInstaller(DummyTool),
#
#         # Add a new type
#         TypeInstaller(factory_type_information2),
#
#         # Add some base content
#         ZexpInstaller('mycontent.zexp', '', set_owner=False),
#
#         # Add all AT types from this product
#         ATTypesInstaller(),
#
#         # Add an External Method in the plone root
#         ExternalMethodInstaller('%s.SomeModule' % PROJECTNAME, 'aFunction', 'anId'),
#
#         # Runs some External methods at install and uninstall
#         ExternalMethodRunner(ext_install=('%s.SomeModule' % PROJECTNAME, 'extraInstall'),
#                              ext_uninstall=(('%s.SomeModule' % PROJECTNAME, 'extraUninstall1'),
#                                             ('%s.SomeModule' % PROJECTNAME, 'extraUninstall2')),
#
#         # Add a role with some permissions
#         RoleInstaller('DummyRole', model='Authenticated', allowed=('Reply to item', 'View')
#
#
# def install(self):
#     # Always start with the creation of the InstallationContext
#     ic = InstallationContext(self, product_globals)
#
#     # Check the availability of some Zope and Plone
#     ic.requiresProduct('ZMySQLda')
#     ic.requiresInstalledProduct('Epoz')
#     ic.requiresInstalledProduct('Archetypes')
#     ic.requiresInstalledProduct('GroupUserFolder')
#
#     # Runs the installation ans return the report
#     return getRunners().install(ic, auto_reorder=1)
#
# def uninstall(self):
#     # Always start with the creation of the InstallationContext
#     ic = InstallationContext(self, product_globals)
#
#     # Runs the uninstallation ans return the report
#     return getRunners().uninstall(ic, auto_reorder=1)

Recommanded order for installers

Doesn't matter a lot in most cases but note that when creating an InstallationRunner object, you should:

o Provide the TypeInstaller(s) before the WorkflowInstaller(s)

o Provide the ToolInstaller(s) before the ActionsInstaller(s)

You may pass the 'auto_reorder=1' argument to the 'install' and 'uninstall' methods of your InstallationRunner object if you want to have your installers automatically reordered in a way that is supposed to be the safest.

Note that uninstalling reverses the order of the executed xxInstallers

Making your own Installer classes

If the CMFQuickInstaller is capable of uninstalling automatically what you intent to install, you must use 'InstallerQISupportBase' as base class for your installer and implement the 'doInstall' method only.

Otherwise, you need to use the 'InstallerBase' as base class for your xxInstaller class, and implement 'doInstall' and 'doUninstall' methods.

In any case, 'doInstall' and 'doUninstall' must have this signature

def doInstall(self, context, **kw)

def doUninstall(self, context, **kw)
o 'context' is the InstallationContext created at the start of your
'install' and 'uninstall' hook functions. You should read the source of utils.InstallationContext class to get all attributes and methods.
o 'kw' is a list of keyword arguments used to override standard
default options as 'stop_on_error', or your class default options.

Example

from Products.PloneInstallation.public import *

__all__ = ('MyStuffInstaller',)

class MyStuffInstaller(InstallerBase):
    def __init__(self, myFeatures, **kw):
        self.myFeatures = myFeatures
        ...
        for k, v in kw.items:
            setattr(self, k, v)
        return

    def doInstall(self, context):
        # Do your own cooking
        context.logInfo("Success !!")

    def doUninstall(self, context):
        # Do your own cooking
        if someProblem:
            context.logWarning("Some problem...")
        if completelyMessedUp:
            context.logError("Aaaargh ! Must stop, sorry!")

Hacking the source code, you'll get more enlightenments making your own xxInstaller class.

Don't hesitate to send me your own xxInstaller classes. They may be added in future versions of this Product (with a mention to the author).

Authors

The "Ingeniweb team":http://www.ingeniweb.com 2005

Feedback

Please report the bugs, features requests (...) at "ingeniweb project of sourceforge.net":http://sourceforge.net/projects/ingeniweb

More information can be found at "the PloneInstallation page":http://ingeniweb.sourceforge.net/Products/PloneInstallation

Download

Released versions

Released versions of PloneInstallation are available here. The current version is 2.1.2.

CVS version

The repository contains the up-to-date versions of our source code. In order to get the HEAD branch of PloneInstallation, use :

svn https://svn.plone.org/svn/collective/PloneInstallation/trunk
          

You can also browse the CVS with your browser.

Documentation

Readme

Please take time the read the Readme

F.A.Q

Q: Why should I use PloneInstallation ?

A: Because you are a developer an you don't want to lose your time writing/testing again and again installation scripts that all look the same but don't do the same thing. With PloneInstallation, you just need to focus on your business logic, not on the installation technical details any more.

Q: I didn't find an installer class that suits my requirements. How should I deal with it?

A: The README.txt explains how to build your own installer class that registers easily within the PloneInstallation framework. Please feel free to send us your own installer classes that are of general interest.

Links

History

PloneInstallation changes

CVS HEAD (Unreleased)
  • ATInstaller: Plone 2.1 compliant. Remove the dependance to registerTemplates and copy the code in the installer.
  • RoleInstaller: Creates a new roles with permissions settings
  • ExternalMethodInstaller: Installs an external method anywhere.
  • ExternalMethodRunner: Executes External Methods in context of the portal at install and/or uninstall time.

0.2RC1 (2005/4/19)

  • A very comprehesive programmer manual in the README.txt
  • ActionsInstaller silently fails on installation/uninstallation of actions when the action provider is not existing. Thanks to Maik Roeder.
  • Added a public.py module to ease global names imports when using the API from products.
  • Added a first version of an ATTypesInstaller class (ATInstaller.py) needed by most current Plone site projects. Thanks to Kamon Ayeva.
  • New "plugin" more rational approach. Installer classes are now in the "installers" folder.

0.1a1

Initial public alpha release

PloneInstallation ChangeLog is also available for detailed informations.

Contact