About PloneInstallation
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)'
'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)'
'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)'
- '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)'
'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)'
- '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)'
- '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)'
- '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)'
- '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)'
- '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)'
- '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)'
- '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)'
'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)'
- '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)'
- '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)'
- '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)'
- '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 2005Feedback
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
- You can report bugs using the bugtracker.
- To get Open Source support for this component, use support@ingeniweb.com.
- To get commercial support for this component, ask sales@ingeniweb.com.
- To host a Zope/Plone server or instance, take a look at IngeniHosting.
- For Zope, Plone or PloneInstallation training, ask sales@ingeniweb.com.