How to get python 2.4 or 2.5 for Ubuntu 10.4

Each new version of an OS carries its bad news. The last version of Ubuntu doesn’t embed neither Python 2.4 nor Python 2.5. Nevertheless until all your Plone sites will be migrated to Plone 4 you will need a Python 2.4 version somewhere.

Method 1: search for sources to get binary packages

There is a Python 2.4 « branch » in Ubuntu on launchpad :  “python2.4” source package in Lucid. If you now a little how Ubuntu packaging work you can easyly get Ubuntu package of Python 2.4 by following steps below:

  1. Click on Show builds
  2. Choose Successfully built then apply the filter
  3. Then choose your the archive for your architecture (often i386 or amd64)

There you have python2.4 and python2.4-dev packages.

Method 2: Use packages search tool

Launchap also have a package search tool for all Ubuntu releases. This one doesn’t limit itself to packages disbributed in official Ubuntu repositories and it also give results for all packages build using the Launchad system.

In our case we can use:

Method 3: Get sources and create your own packages

From the source page of the first method (“python2.4” source package in Lucid) you can get sources and the official patch for Ubuntu. For exemple you can click on 2.4.6-1ubuntu5 to get this version.

On the next page you can download a python source archive and the associated patch :

Once these to files downloaded you will do following steps:

  1. Unarchive python sources: tar zxf python2.4_2.4.6.orig.tar.gz
  2. Uncompress the patch:  gunzip python2.4_2.4.6-1ubuntu5.diff.gz
  3. Apply the patch:  patch -p0 < python2.4_2.4.6-1ubuntu5.diff
  4. Go in the folder created: cd python2.4-2.4.6
  5. Try to build the package: dpkg-buildpackage
  6. Install libreadline5-dev or fix the debian/control file by replacing libreadline5-dev by libreadline-dev (I’m nasty)
  7. Install all dependencies required (why do you need emacs and bluetooth to compile python ?): apt-get install libncursesw5-dev  tk8.5-dev libdb4.6-dev libgdbm-dev blt-dev  libbluetooth-dev emacs23 debiandoc-sgml
  8. Try again to build the package: dpkg-buildpackage

I don’t know how long these packages will be available.


Add a new role in the sharing tab for Plone 3

If you want to display a new role in the sharing tabe of Plone 3 it requires a
good knowledge of ZCA. First you need to create another specific role then an
utility. These complexity allows you to control which roles are displayed
using workflows.

Lets take the example of the well known Manager role.

Create the delegating role

First you have to define a new role. The auto defined convention said that it
should be named as Sharing page: Delegate XXX role. As often you need to
register this new role both in Python and ZCML:

# -*- coding: utf-8 -*-
from Products.CMFCore.permissions import setDefaultRoles
from AccessControl import ModuleSecurityInfo

security = ModuleSecurityInfo("my.egg.permissions")

DelegateManagerRole = "Sharing page: Delegate Manager role"
setDefaultRoles(DelegateManagerRole, ('Manager',))


<configure xmlns=""

    <!-- Our custom permissions -->
        title="Sharing page: Delegate Manager role"


Create your Role utility

Now you have a delagating role to control how to share your role you need to
create an utility that implements the ISharingPageRole interface. This
interface requires two attributes:

  • title: a translated title
  • required_permission: the permission defined just before

# -*- coding: utf-8 -*-
from zope.interface import implements
from import ISharingPageRole

from my.egg import permissions
from my.egg import MyEggMessageFactory as _

class ManagerRole(object):

    title = _(u"title_can_manage", default=u"Can manage")
    required_permission = permissions.DelegateManagerRole

At last we have to register this utility and the permissions.zcml defined


<include file="permissions.zcml" />

  <!-- Local roles managed in the @@sharing view -->

By default the sharing tab hide Manager, Owner and Member role
because they can create troubles when they are used in a wrong way. If you
think to show them be sure that persons that will use it are informed how they
can put their site upside down.

Mise au point sur la licence GPL et les services web

J’avais déjà fait un billet à ce sujet il y a quelques temps. Lors des Journées du Logiciel Libre j’ai eu l’occasion de discuter avec Alix Cazenave après sa conférence sur la loi Hadopi et le contrôle du net.

Voici les points que j’ai pu éclaircir :

  • la licence GPL concerne le code d’un logiciel
  • les services web ne sont pas couverts par la licence GPL
  • c’est la licence Affero GPL qui couvre les services réseau

Lorsqu’une entité mets en œuvre des services réseau basés sur du code GPL elle n’a aucun devoir de partage du code source de son application avec ses utilisateurs ou avec la communauté. Cette entité peut vendre les services réseau sans contreparti mais si elle veut vendre l’installation de son application il lui faudra partager les sources.

Si le code d’un logiciel est protégé par la licence Affero GPL alors n’importe quel utilisateur interagissant avec service réseau basé sur son code peu demander le code source complet du service réseau.

Dans le cas de Plone 2 et de Plone 3 ils ne relèvent que de la seule licence GPL. Plone 4 utilisera sûrement une licence BSD lors de sa sortie.

Which Plone project is your site based on?

Far from the versions war I’m trying to understand how many people don’t use Plone « main » and choose to use project based on it. This evaluation is getting more difficult that I’m not able to recense how many projects are based on Plone. We can found some of them in the feed and some others in pypi or in the products column.

I can easily cite :

But they would be much more.

The Plone Conference in Budapest will be a good place for these projects to gain visibility and to project leaders to talk with the evangelist team to gain a page on to show what are their roadmap. It is difficult to find an announce done in a feed or in mailing lists few months ago. It easier to find a page one the official site if a projects column is created in it. The Plone foundation doesn’t have to fund them, but can help their communication.

Manage monkey patches and performance improvement in Plone 3

Few days ago Jean-Michel François proposed a useful patch for PlonePAS that can be applied for all Plone release until 3.2. Plone 3.3 will embed this patch.

How can we add this patch in a traceable way for an not so old Plone 3.1 or 3.2 ?

First, we can use the new release  of Products.PlonePAS that should be compatible with our Plone installation. The second option is to add a monkey patch in the policy product of our site. One more monkey patch…

Some projects have so many monkey patches that it is difficult to know where is the code that run your site. Martin Aspeli did a tool to handle monkey patches in an elegant way for Zope 2 and Zope 3: collective.monkeypatcher. It allows you to plug  your monkey patches with a simple ZCML directive. Later Gilles Lenfant added a control panel for Zope 2 to be able to have a visual way to follow patches with collective.monkeypatcherpanel.

How does it works?

In your buildout.cfg add :

eggs +=
zcml +=

To create patches add a ‘‘ file in your egg (if you have more than 2 or 3 patches you should create a directory). Our performance patch looks like this:

import copy

def enumerateUsers( self
                  , id=None
                  , login=None
                  , exact_match=False
                  , **kw

    """ See IUserEnumerationPlugin.
    plugin_id = self.getId()

    if id is not None:
    if login is not None:

    if not kw and id:
        data = self._storage.get(id, None)
        if data is None:
            user_info = []
            user_info=[ { 'id' : self.prefix + id,
                     'login' : id,
                     'title' : data.get('fullname', id),
                     'description' : data.get('fullname', id),
                     'email' : data.get('email', ''),
                     'pluginid' : plugin_id } ]
        users=[ (user,data) for (user,data) in self._storage.items()
                    if self.testMemberData(data, criteria, exact_match)]

         user_info=[ { 'id' : self.prefix + user_id,
                     'login' : user_id,
                     'title' : data.get('fullname', user_id),
                     'description' : data.get('fullname', user_id),
                     'email' : data.get('email', ''),
                     'pluginid' : plugin_id } for (user_id, data) in users ]

        return tuple(user_info)

In the configure.zcml of your policy product add an include:

<include file="patches.zcml" />

The file patches.zcml will contain following code:


    <include package="collective.monkeypatcher" file="meta.zcml" />



Run your buildout, start your site and the patch is applied. You can go in the Zope Control Panel to see how many patches are already compatible with this tool.

Heads up: new plone.recipe.pound release

Since few weeks plone.recipe.pound 0.5.4 was broken with an output like this:

An internal error occured due to a bug in either zc.buildout or in a recipe being used:
Traceback (most recent call last):
File "/tmp/tmpVcq-b1/zc.buildout-1.2.1-py2.4.egg/zc/buildout/", line 1509, in main
File "/tmp/tmpVcq-b1/zc.buildout-1.2.1-py2.4.egg/zc/buildout/", line 473, in install
File "/tmp/tmpVcq-b1/zc.buildout-1.2.1-py2.4.egg/zc/buildout/", line 1091, in _call
File "/home/encolpe/.virtualenvs/internal/preprod/plone.recipe.pound/plone/recipe/pound/", line 74, in install
installed = CMMIRecipe.install(self)
File "/home/encolpe/.virtualenvs/internal/preprod/downloads/dist/zc.recipe.cmmi-1.2.0/src/zc/recipe/cmmi/", line 155, in install
system("make install")
File "/home/encolpe/.virtualenvs/internal/preprod/downloads/dist/zc.recipe.cmmi-1.2.0/src/zc/recipe/cmmi/", line 27, in system
raise SystemError("Failed", c)
SystemError: ('Failed', 'make install')

This recipe directly unherit from zc.recipe.cmmi and act as a wrapper around the CMMIRecipe.install method. Most arguments used are transmitted to the recipe are self attributes or keys in self.options. The version 1.2.0 of this recipe publish the May, 18 moved the way that extra arguments are transmitted:

  • zc.recipe.cmmi 1.1.x:  self.options[‘extra_options’]
  • zc.recipe.cmmi 1.2.0: self.extra_options (an empty string by default)

There’s no regression tests, neither an entry in the release history. Youenn did a new release of plone.recipe.pound to fix this new behavior.


  • if you are using zc.recipe.cmmi 1.1.x you can still use plone.recipe.pound 0.5.4
  • if you are using zc.recipe.cmmi 1.2.0 or above use plone.recipe.pound 0.5.5
  • other recipes using zc.recipe.cmmi may be broken

‘Practical Plone 3’ review

I finished to read the long waited (read updates here 🙂) ‘Practical Plone 3’ book. It reprensents a big amount of very good work.

If you want to begin in Plone or if you want a webmaster guide for your brand new Plone site the two first parts are designed for you. Each step of your needs are describe in a very good teaching way.

Parts are growing in difficulties. The first will show you how to install and what in installed in a default Plone site. The second part will learn you how to become the owner of your site by creating content and configuring it. The third part is for those who wanted to learn how to use addon products for Plone or want to customize Plone site: zc.buildout, PloneFormGen and ArchGenXML are presented here. The last part will show you some general needs around Plone: put Plone in production behind Apache or IIS with speed optimizations, and LDAP/Active Directory integration.

Even if the target of this book is beginners it was a very interresting reading for an old developper like me. If you don’t use it for yourself, you will use it to give answers to your end-users. I can only recommand everyone to buy it. Nice work guys.

Why Plone architecture must change

I proposed a conference on this theme but it was not keeped for PloneConf2008. Here comes a short work on its, and I will hope it create a debate.

Plone is born with a goal: make Zope 2 and CMF simple. Those two are frameworks and allowed you to create a website… a so rustic website. With Plone you only needed to fill one form to have a cool site ready to use and to custom. At that time Plone was CMFPlone, an other implementation of CMFDefault.

Some new products were inserted in the bundle like GroupUserFolder in a such way that they cannot be separated from the base implementation of Plone.

The second step was the Archetypes framework: a new manner to manage object’s attributes as schema. With all informations stored in the schema,  mutators and accessors are generated on boot time and forms are generated from schema’s widgets. It was cool, but not perfect. Then the product ATcontentTypes was created to be the glue to upgrade CMFPlone as Plone: all base types from CMF are now overloaded by a type from ATContentTypes.

So came Zope 3 and Five. Five is the glue that allows Zope 2 developpers to use component architecture from Zope 3 in their code. Plone 2.5 and Plone 3 are using Five.

Another product came from Zope ‘renegades’: PluggableAuthService and its implementation in Plone: PlonePAS. It should replace the old GroupUserFolder but users and groups management templates were never refactored.

Plone 3 introduces new component in to our greatest happiness.

What part of Plone needs CMF?
Why Plone needs to know about Archetypes storage and CMFEditions strategy?
Why GroupUserFolder is always in the bundle as PlonePAS fit is API?

Now Plone is like the linux kernel: a big monolithic Plone with a lot of modules that create a base Plone 3 site. And so much glue! GroupUserFolder is always here because nobody knows and wants to work on the portal_group replacement.
If you are following Plone4Artist or PloneGov you can see that a part of these projects needs to overload Plone base configuration.

CPS 3, an other CMF-based CMS, was conceived with the thinking that components need to be independant to be reusable and maintainable:

  • CPSSchema depends only on Zope
  • CPSCore depends only on Zope
  • CPSDocument depends only on CPSSchema
  • CPSDefault depends on CPSCore and CPSSchema, and implements the CPS site.

After 2 years it was divided into platforms:

  • CPS Legacy
  • CPS Courier
  • CPS Groupware

In front of that Plone propose at single product with a lot of glue that depends on others products or components that use their own glue and so on…
There’s no plone.core and plone.default and we cannot create a plone.artistsite or a plone.govsite.
Do you think that everyone need an openid or an ldap integration in Plone ?

Plone 4 must be a reimplementation, not only a new glue with new concepts. I don’t want any new functionality in Plone 4, I want modularity and scalability.

Write functionnal doctests with files in forms

A short bill about testing forms with files.

First you need to setup you environment using your site policy product then your
product to test. The function setUpDefaultMembersAndFolder create the
structure with access rights positioned. After that you can focus yourself on
Formula module test.

Test Formule creation process

For the test you need to create three Nomenclatures and two Validation Process.

First, some set-up:

    >>> from Products.Five import zcml
    >>> import Products
    >>> import iw
    >>> zcml.load_config('configure.zcml', package=iw.sitepolicy)
    >>> zcml.load_config('configure.zcml', package=Products.Formula)

    >>> from iw.sitepolicy.tests import utils
    >>> utils.setUpDefaultMembersAndFolder(self)

    >>> from Products.Five.testbrowser import Browser
    >>> browser = Browser()
    >>> browser.handleErrors = False

Let us log all exceptions, which is useful for debugging. Also, clear portlet
slots, to make the test browser less confused by things like the recent portlet
and the navtree.

    >>> self.portal.error_log._ignored_exceptions = ()
    >>> self.portal.left_slots = self.portal.right_slots = []

Import needed for testing file in forms

    >>> import cStringIO
    >>> portal_url = self.portal.absolute_url()

We will need of cStringIO to create fake files.

Now we will logon with an user and jump directly into working folder.

    >>>'%s/logout' % portal_url)
    >>> + '/login_form')
    >>> browser.getControl('Login Name').value = 'jdoe'
    >>> browser.getControl('Password').value = 'secret'
    >>> browser.getControl('Log in').click()
    >>> 'John Doe' in browser.contents
    >>> browser.url

Verify that an author keeps modification and creation rights

    >>> self.formula_folder.absolute_url()+'/edit' in browser.contents

    >>> self.formula_folder.absolute_url()+'/createObject?type_name=BaseFormula' in browser.contents

self.formula_folder is set in setUpDefaultMembersAndFolder.

Now we can fill the form and test the result. Document’s id is the filename
prefixed by ‘formula_‘ and document’s title is the first file line.

Create a new Formula for with special pink flavor

    >>> browser.getLink('Add Base Formula').click()
    >>> 'portal_factory' in browser.url
    >>> browser.getControl(name='special').value = u"pink flavor"
    >>> browser.getControl(name='formula_file').add_file(cStringIO.StringIO('Pink flavor\n   etc'), 'text/plain', "32048432.txt")
    >>> browser.getControl('Save').click()
    >>> 'Changes%20saved' in browser.url
    >>> browser.getLink('View').click()
    >>> '<h1>Pink flavor</h1>' in browser.contents
    >>> print browser.url

If you want to do the same with Plone 2.5 – Zope 2.9 – you will have an error
because the ‘add_file‘ is not implemented on FileControl. You need to use
following code: