Plone as egg
============

This is an attempt to package Plone up as an egg.

Building the egg
----------------

1) Checkout a bundle of Plone that contains all the necessary products in
   the ``Products/`` subdirectory

2) Run ``setup.py bdist_egg``.  This requires you to have setuptools_
   installed.

The egg should be now in ``dist/Plone*egg``, ready for installation.
You can distribute your egg at this point.

Note: Currently there is a problem that prevents ATContentTypes'
``thirdparty`` package from being included.  This should probably be
fixed in ATContentTypes.  For now, you need to put an empty
``__init__.py`` file into the ``Products/ATContentTypes/thirdparty``
directory.

.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools

Installing the egg
------------------

You can install the egg site-wide.  With the effect that the Products
will be available for import *implicitly* for every Zope 2 instance in
the site.  Doing this is very simple::

    easy_install dist/Plone*egg

Because Zope 2 will automatically scan all packages inside
``Products``, there is no way to control exclusion of a Product in
your instance.  This is less than ideal.  If our Product were not to
use Zope2's Products namespace (which is well doable using Rocky
Burt's pythonproducts_), we could have more control of what is
included, using Five's new ``registerPackage`` directive.  (Note that
pythonproducts was merged into Five.)

Now that all packages in Plone use the Products namespace, we'll have
to think about a way to deal with this.  Fortunately, easy_install
comes with the `--multi-version
<http://peak.telecommunity.com/DevCenter/EasyInstall#command-line-options>`_
command line option, which allows you to have more control over which
packages are available at runtime.

Using --multi-version, we can install our egg into the instance's
``lib/python`` directory to effectively make our egg only available in
that instance::

    easy_install --multi-version \
                 --install-dir=$INSTANCE_HOME/lib/python/ \
                 --site-dirs=$INSTANCE_HOME/lib/python/ \
                 dist/Plone*egg

When you install something ``--multi-version``, client code that uses
your package has to be aware of that and do an explicit ``import
pkg_resources; pkg_resources.require(name)``.  In our example, we need
to ``require('Plone') somewhen`` in our Zope process.  I had the idea
of requiring packages in zcml, similiar to how pythonproducts
registers ordinary Python packages as Products.  There's a pending
patch for pythonproducts that enables this, although pythonproducts is
maybe the wrong place to implement this::

  Index: src/pythonproducts/fivedirectives.py
  ===================================================================
  --- src/pythonproducts/fivedirectives.py	(revision 26757)
  +++ src/pythonproducts/fivedirectives.py	(working copy)
  @@ -16,6 +16,7 @@
   """

   from zope.interface import Interface
  +from zope.schema import BytesLine
   from zope.configuration.fields import GlobalObject


  @@ -35,4 +36,11 @@
                       u'with a ProductContext instance',
           required=False
           )
  -    
  \ No newline at end of file
  +
  +class IRequireDistributionDirective(Interface):
  +    """pkg_resources.require() a distribution."""
  +
  +    name = BytesLine(
  +        title=u'Target distribution',
  +        required=True,
  +        )
  Index: src/pythonproducts/meta.zcml
  ===================================================================
  --- src/pythonproducts/meta.zcml	(revision 26757)
  +++ src/pythonproducts/meta.zcml	(working copy)
  @@ -12,6 +12,12 @@
          handler="Products.pythonproducts.pythonproducts.registerPackage"
          />

  +    <meta:directive
  +       name="requireDistribution"
  +       schema="Products.pythonproducts.fivedirectives.IRequireDistributionDirective"
  +       handler="Products.pythonproducts.pythonproducts.requireDistribution"
  +       />
  +       
     </meta:directives>

   </configure>
  Index: src/pythonproducts/pythonproducts.py
  ===================================================================
  --- src/pythonproducts/pythonproducts.py	(revision 26757)
  +++ src/pythonproducts/pythonproducts.py	(working copy)
  @@ -37,6 +37,13 @@
           args = (package,initialize)
           )

  +def requireDistribution(_context, name):
  +    """ZCML directive function for requiring a distribution using
  +    pkg_resources.
  +    """
  +    
  +    import pkg_resources
  +    pkg_resources.require(name)

   def _registerPackage(module_, initFunc=None):
       """Registers the given python package as a Zope 2 style product


After applying this patch to your pythonproducts installation, you can
go ahead and include Plone in your instance using zcml.  Create a
``$INSTANCE_HOME/etc/package-includes/plone-configure.zcml`` file and
put the following in it::

  <configure xmlns="http://namespaces.zope.org/zope"
             xmlns:five="http://namespaces.zope.org/five">
      <five:requireDistribution name="Plone" />
  </configure>

Please refer to the pythonproducts README for details on where to add
zcml and why.

Now start up your Zope and hopefully see Plone getting loaded.

Note that for packages which are not in the Products namespace
package, i.e. for Product-less Python packages you would need to use
pythonproducts' ``registerPackage`` directive as well.  (Which is a
good thing.)  For these packages, the whole process becomes a lot
easier, because you can just ``easy_install`` away and be done, **or**
if you need instance- specific versions/packages, use --multi-version
and the ``requireDistribution`` directive.

.. _pythonproducts: http://plone.org/products/pythonproducts
