You are here: Home Articles Release-fest - the importance of small products
OpenID Log in


Release-fest - the importance of small products

by Martin Aspeli last modified Apr 17, 2009 03:32 AM

Lots of small packages makes everyone happy

For a while, whilst in the main thrust of development for my current project, I was releasing two products a day. My terminal buffer willed with 'paster create -t plone' and the collective and plone svn logs grew longer.

This was part of a conscious strategy. The solution we are building is meant as a platform to be customised in individual deployments. By factoring "services" out into separate packages and releasing those to the community, we can focus on the packages that are specific to your use case and configuration. The "client-specific" code runs to only a few hundred lines. Most of the system is assembled through the web for each deployment, with portlets, dashboards, collections, content pages and so on.

Furthermore, writing small, re-usable packages that work with "plain Plone" made it easier to write tests and avoid "functionality bleed", leading to more focused and higher quality code. Plus, it's a lot more fun to write something generally useful and share it with the community, getting feedback and discussing design up front. :)

The end result is a pretty long list of packages. They can all be found on PyPI (forgive me for not linking to each one individually), and I will release the relevant ones to soon, I promise. ;)

  • collective.monkeypatcher - a small package to make it easier to apply monkey patches from ZCML
  • plone.registry - an infrastructure component to manage settings registries ala about:config in Firefox. This one's likely to be part of Plone 4.
  • - UI support for the above, with helpers for making control panel forms and a generic settings editor
  • - lets you describe member data settings via zope.interface schemata, with automatically generated preferences edit forms
  • collective.autopermission - depend on and ZCML include this, and you can define entirely new permissions in ZCML using the <permission /> statement (this functionality is now folded into Five for Zope 2.12)
  • collective.wfcomment - uses JavaScript to encourage users to enter a comment when they enact a workflow transition from the 'state' drop-down
  • - define sane workflows through CSV files (existed before, but updated for this project)
  • collective.subtractiveworkflow - a workflow for taking away permissions (e.g. to mark content as confidential)
  • collective.membercriterion - a Collection criterion for comparing an indexed value to a member property (we use this with collective.memberschema to let users define tags they're interested in, and have collections show content matching those tags)
  • collective.sharingroles - a GenericSetup import/export syntax for managing which roles show up on the sharing tab
  • collective.portlet.contribute - a portlet to entice people to add content in a given folder (we put this on group dashboards to direct people to add content in specific folders)
  • collective.portlet.workflowsteps - a portlet to show details of the current state and available transitions, in rich HTML with variable interpolation to allow links to more information etc
  • collective.portlet.truereview - a review portlet that takes into account whether the user has the 'Review portal content' permission over the content item or not
  • collective.groupdashboard - manage dashboards per-group in addition to per-user (we use this to create a common dashboard for all content contributors, all reviewers, all administrators and so on)
  • collective.discussionplus - extensions to Plone's commenting infrastructure to support workflow (moderation) and better indexing
  • collective.novate - a small form, linked form the Sharing tab, to allow users to change ownership of a content item, using an auto-complete widget
  • collective.contentrules.parentchild -- content rule conditions and actions to make assertions about child objects ("child of type/workflow state exists") and make changes on the parent ("transition parent", "invoke auto-transitions on parent")
  • collective.contentrules.template - content rule action to automatically create content based on a template item
  • plone.principalsource - a queriable source for users, groups or both (principals) - underpins collective.novate
  • plone.namedfile - a zope.schema-type field for blob and non-blob images and files
  • plone.formwidget.namedfile - z3c.form widget for the above
  • collective.xdv - in-Plone deliverance transforms using the xdv engine, with a control panel to designate which domains invoke theming and expressions for use in the portal_css tool to control which CSS files filter through to the themed site
  • dv.xdvserver - supports running xdv as a standalone server for development purposes

Please note that a number of these (collective.xdv, plone.formwidget.namedfile, collective.novate,,  depend on plone.autoform, which in turn depends on plone.z3cform and z3c.form, and will give the most Plone-ish results. To use these, you will need to add a few version pins to your buildout, since plone.z3cform depends on newer versions of some core components. Something like this should work:

versions = versions

z3c.form = 1.9.0
zope.i18n = 3.4.0
zope.testing = 3.4.0
zope.component = 3.4.0
zope.securitypolicy = 3.4.0 = 3.4.3


For plone.namedfile you may also want to pin z3c.blobfile to version 0.1.2

Document Actions

Posted by at Apr 19, 2009 11:44 AM
Dear Martin,

this strategy of a lot of small products seems to be very useful indeed. immediately caught our attention as a simpler alternative to membrane/remember (which we were thinking about using) and we tried to use it with plone 3.2.2. We added it to our buildout with the version pinning you mention, but ran into some problems with ZODB3 and zope.proxy.

- Does this depend on Zope-2.11.2 instead of Zope-2.10.7? Using 2.11.2 seems to solve a problem with missing ZODB.blob.

- Do we need to use skip-fake-egg for zope.proxy? This seems to solve a problem with missing zope.proxy.decorator.

With these changes, we managed to get plone to start on a linux box but not on a mac box (missing ZODB.Mount), with the same buildout.

Also, on the plone that started, accessing the view @@my-profile gives the following error:

ComponentLookupError: ((<Products.Five.metaclass.MyProfileView object at 0xabc13d0>, <HTTPRequest, URL=http://localhost:10080/teste/@@my-profile>), <InterfaceClass zope.pagetemplate.interfaces.IPageTemplate>, u'')

Did we mess up something that should be simpler?

Posted by Martin Aspeli at Apr 20, 2009 11:28 AM
I'd skip all the blob stuff - disable and the ZODB3 egg update and zope.proxy. They're probably not needed for

The error suggests that you don't have installed or loaded, because it can't find the default template. I thought it was a dependency of, but maybe not? Maybe worth loading it explicitly to check.

Posted by at Apr 21, 2009 02:00 PM
Thank you for your attention. Indeed, adding explicitly solved the ComponentLookupError.

Regarding the blob problem, seems to depend on plone.namedfile, which depends on z3c.blobfile and fails with missing ZODB.blob, unless we load zodb3 with zope 2.11.2 (and even then, it fails on a mac box, but not on linux box). Is it supposed to work on zope 2.10.7?

Posted by Martin Aspeli at Apr 22, 2009 04:36 AM
That makes sense.

I don't use ploneZope 2.11.2, but I do use 2.10 w/ an upgraded ZODB3 egg (add ZODB3 to skip-fake-eggs and add a version pin override for ZODB3 = 2.9.1 or whatever the latest version is). The end result is the same.

Sponsor message

Thoroughly researched reviews of cheap web hosting providers, which also provider domain name registration services and dedicated server offers for complex websites.

Plone Book
Professional Plone 4 Development

I am the author of a book called Professional Plone Development. You can read more about it here.

About this site

This Plone site is kindly hosted by: 

Six Feet Up