Downsides of moving from Products to lib/python?

Martin Aspeli optilude at
Sat Aug 25 11:13:00 UTC 2007

Maurits van Rees wrote:
> Hi,
> The lib/python directory of a Zope instance seems to become a popular
> place for putting things and rightfully so.  I can imagine that in a
> few years time the Products dir becomes totally empty and that zope
> only uses packages in lib/python.

I hope so. :)

> But I wonder if there are (perhaps temporarily) downsides to that.
> I bumped my toe the past week with two such issues:
> 1. zcml files are not loaded automatically.  This is no big deal
>    really, as there are a few ways to solve this:
>    - You can do an <include package="..." /> in a zcml file somewhere
>      in the Products dir.
>    - I heard ploneout does some hacking to the path to make sure these
>      zcmls in lib/python get loaded too.


But the plone.recipe.zope2instance recipe (like it's zope 3 equivalent) 
has an option 'zcml' where you can list package names for which ZCML 
slugs get installed automatically. This is not a hack. :)

The wider point here is that if you're working with eggs (and you will 
be, since third party products are starting to move to eggs) you 
probably want something a bit more egg-aware than dumb old instances. I 
strongly favour zc.buildout here, because it meets all those needs and 
makes sure the right packages (and the right packages only) are 
installed for Zope to run.

I keep promising more documentation on this (and I will, once I'm done 
with the book, which also covers it), but see this post:

>    - You can put zcml "slugs" (one-liners) in etc/site.zcml or
>      etc/package-includes/

The approach I prefer and advocate is to have *one* slug for a "policy" 
product (Wichert calls this a "deployment product"). This has a 
configure.zcml that includes other dependencies as and when needed. It 
also has an installation step that installs other packages as 
dependencies when the policy is installed from the quickinstaller.

Trust me - automatically loading things can lead to just as many 
headaches. Obviously, you want the core Plone stuff to load in 
lock-step, but sometimes other packages can do things that e.g. affect 
your package's tests or setup.

The main benefit I see of using eggs and non-flat namespaces is that it 
makes it much easier to manage things as sets of related packages, 
rather than big monoliths. $INSTANCE_HOME/Products/ was becoming *very* 
crowded, and people didn't split things up into more reusable, managable 
chunks. We saw that happen *a lot more* in the Plone 3 release, when 
people could create a package with paster. :)

See also:

> 2. Translations from i18n and locales directories do not get loaded.
>    You can add <i18n:registerTranslations directory="locales" /> and
>    then that will get loaded, but this is done in a Zope 3 way that is
>    not getting picked by the Zope 2 or Plone translation machinery.
>    For starters, the po files do not get listed in the PTS in the
>    Zope Control Panel.
>    Plone 3.0 of course has templates in lib/python that need
>    translations.  But those translations are in
>    Products/PloneTranslations, so they get picked up as usual.
>    So if you want to have a package in lib/python that needs
>    translation, then you will also have to make a Product for the
>    Products dir that contains the actual translations.

I'm not really too familiar with this. It sounds like a bug to me. :)

> So I have two questions really:
> A. Is there a way to have po files in lib/python get picked up by
>    Zope 2 after all?
> B. Are there more of these gotchas that developers should know?

When writing tests for packages that are also Zope 2 products, you can't 
use ZopeTestCase.installProduct('my.package'); the pattern I prefer is 
as follows:

That is:

  - Any old-style products that need to be loaded for the test goes at 
module level as before:


  - After that, a *deferred method* is used to load packages. Note that 
this ONLY necessary if the package is a product, e.g. it uses 
<five:registerPackage /> to get skins, GS profiles or other product-like 
features. This can also be used to load specific ZCML files.

  - Then, we call setupPloneSite() as normal, telling it to install any 
products (including packages that are products). Note that in Plone 3, 
this also works for packages without an, if they have a GS 
profile, you don't need to do a separate extension_profiles=[] argument.

This approach ensures that the package is loaded and installed only once 
for the test fixture, making tests much faster.


Acquisition is a jealous mistress

More information about the Product-Developers mailing list