skip to navigation
skip to content

buildout.eggnest 0.2

buildout extension to auto load eggs

buildout.eggnest
=================


The problem
-----------
It is very convenient to install functionality to a buildout with just
a couple of lines, but for those used to Zope 2, one might miss
the way of adding a piece of functionality by just dropping something
(i.e. a product) into a folder. This could be good for people who want to try
out things without worrying about editing a configuration file with
lots of directives in it.
When wanting to install a new egg using buildout you currently have to
edit the buildout configuration file(s) and add a couple of lines in
the right places. What if you could just drop a file in a folder instead?

Solution
--------
Make a buildout extension so that the only thing you need to do in order to install an egg
is to take a simple text file, and drop it in a certain directory. When you rerun buildout the
contents of that file is parsed, the specified egg is downloaded and added to the instance.

When ``buildout.eggnest`` is run it::

  1. If ``eggnest-src-directory`` is not given the default directory ``src``
     is scanned.

  2. Adds the egg to the ``eggs`` and ``zcml`` option to a set of given buildout parts.

This steps are done on the fly when running buildout. So I can add/delete/rename
an egg and it will be picked up.

NOTE: The extension does not write to the buildout's configuration file.

buildout.eggnest options
-------------------------

eggnest-src-directory:
 Specified to the directory that your egg install files should be placed.
 Defaults to src. An idea could be
 to have a dedicated directory called "eggnest".

eggnest-parts:
 What part of your buildout config that the eggs should be added to. *required*

eggnest-verbose:
 Set this to ``true`` to get more information.
 Not really that much right now but a little bit more at least.


How to use it
-------------

To use ``buildout.eggnest`` you need to add the following to your buildout.cfg::

  [buildout]
  extensions =
    buildout.eggnest

  eggnest-parts =
    instance

In ``eggnest-parts`` you need to specify what buildout part that the eggs should be added to.
By default the ``src`` directory is scanned for egg specification files.


eggs specification files for eggnest
------------------------------------

The egg install specification files should have this structure. This is the same as the normal buildout config format.::

  [eggnest]
  egg =
    plone.introspector

  zcml =
    plone.introspector

``zcml`` can be multiple lines if additional slugs need to be specified.

If the egg is in the ``Products`` namespace the zcml is not needed in the specification file.::

  [eggnest]
  egg =
    Products.DocFinderTab



buildout.eggnest was created by Martin Lundwall  after an
initial idea by Jorgen Modin 

Change history
================

0.2 (unreleased)
----------------

 - Compatibility update for zc.buildout 1.4.0 (mlundwall)

0.1 (2008-11-22)
----------------

  - Initial release (mlundwall)
Detailed Documentation
======================

Tests for buildout.eggnest buildout extension
-------------------------------------------------

Let's create a buildout configuration file::

    >>> data = """
    ... [buildout]
    ... parts = zope2 instance1 instance2 instance3
    ... extensions =
    ... eggs =
    ... develop = %s
    ... eggnest-parts = instance1 instance2
    ... [instance1]
    ... recipe = plone.recipe.zope2instance
    ... zope2-location = ${zope2:location}
    ... user = admin:admin
    ... [instance2]
    ... recipe = plone.recipe.zope2instance
    ... zope2-location = ${zope2:location}
    ... user = admin:admin
    ... [instance3]
    ... recipe = plone.recipe.zope2instance
    ... zope2-location = ${zope2:location}
    ... user = admin:admin
    ... [zope2]
    ... recipe = plone.recipe.zope2install
    ... url = http://www.zope.org/Products/Zope/2.9.8/Zope-2.9.8-final.tgz
    ... """ % egg_dir
    >>> rmdir(tempdir, 'buildout.test')
    >>> cd(tempdir)
    >>> sh('mkdir buildout.test')
    mkdir buildout.test
    
    >>> cd('buildout.test')
    >>> touch('buildout.cfg', data=data)
    >>> ls('.')
    buildout.cfg

run the buildout first time so we get our zope instances::

    >>> sh('svn export svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap/bootstrap.py')
    svn export svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap/bootstrap.py
    A    bootstrap.py
    Export complete.
    
    >>> sh('python2.4 bootstrap.py')
    python2.4 bootstrap.py
    ...
    Creating directory '/private/tmp/buildout.test/bin'.
    Creating directory '/private/tmp/buildout.test/parts'.
    Creating directory '/private/tmp/buildout.test/develop-eggs'.
    Generated script '/private/tmp/buildout.test/bin/buildout'.
    

    >>> sh('./bin/buildout')
    ./bin/buildout
    ...
    Installing instance1.
    ...
    Installing instance2.
    ...
    Installing instance3.
    ...
    
    

Now let's create a test products specification file and add the buildout.eggnest as an extension::

    >>> sh('mkdir src')
    mkdir src
    
    >>> product = """
    ... [eggnest]
    ... egg =
    ...     plone.portlet.static
    ... zcml =
    ...     plone.portlet.static
    ... """
    >>> touch('src/product.txt', data=product)
    >>> ls('src')
    product.txt
    >>> data = data.replace('extensions =', 'extensions = buildout.eggnest')
    >>> touch('buildout.cfg', data=data)


Ok, so now that we have an egg, lets run the buildout in offline mode. We
should get a zcml slugs in parts/instance1/etc/package-includes and parts/instance2/etc/package-includes
but not in parts/instance3/etc/package-includes,
and a line with the path to our egg in the bin/instance1 and bin/instance2
but not in bin/instance3 files.

First we check that there is nothing of the previous mentioned things::

    >>> ls('develop-eggs')
    buildout.eggnest.egg-link
    >>> ls('parts/instance1/etc/package-includes')
    No directory named parts/instance1/etc/package-includes

    >>> ls('parts/instance2/etc/package-includes')
    No directory named parts/instance2/etc/package-includes

    >>> ls('parts/instance3/etc/package-includes')
    No directory named parts/instance3/etc/package-includes

    >>> sh('grep plone.portlet.static bin/instance1')
    grep plone.portlet.static bin/instance1
    

    >>> sh('grep plone.portlet.static bin/instance2')
    grep plone.portlet.static bin/instance2
    

    >>> sh('grep plone.portlet.static bin/instance3')
    grep plone.portlet.static bin/instance3
    

OK, now run the buildout in offline mode::

    >>> sh('./bin/buildout')
    ./bin/buildout
    ...

Check that we have a correct created buildout.

Check that we have our zcml slugs in the package-includes::

    >>> ls('parts', 'instance1', 'etc', 'package-includes')
    001-plone.portlet.static-configure.zcml

    >>> ls('parts', 'instance2', 'etc', 'package-includes')
    001-plone.portlet.static-configure.zcml

    >>> ls('parts', 'instance3', 'etc', 'package-includes')
    No directory named parts/instance3/etc/package-includes


and in the end check that there is a line in bin/instance1 and bin/instance1
that includes our egg in the path::

    >>> code = cat('bin', 'instance1', returndata=True)
    >>> code.find('plone.portlet.static') == -1
    False

    >>> code = cat('bin', 'instance2', returndata=True)
    >>> code.find('plone.portlet.static') == -1
    False

    >>> code = cat('bin', 'instance3', returndata=True)
    >>> code.find('plone.portlet.static') == -1
    True

Let's now try the ``eggnest-src-directory`` option. We create a new buildout.cfg file
with an empty ``eggnest-src-directory``::

    >>> data = data.replace('eggs =', 'eggnest-src-directory = \neggs = ')
    >>> touch('buildout.cfg', data=data)
    >>> sh('./bin/buildout')
    ./bin/buildout
    ...


No zcml slug in the instance 1,2 or 3::

    >>> ls('parts', 'instance1', 'etc', 'package-includes')
    No directory named parts/instance1/etc/package-includes

    >>> ls('parts', 'instance2', 'etc', 'package-includes')
    No directory named parts/instance2/etc/package-includes

    >>> ls('parts', 'instance3', 'etc', 'package-includes')
    No directory named parts/instance3/etc/package-includes

Nor a line in bin/instance1, bin/instance2 or bin/instance3 with our egg path::

    >>> code = cat('bin', 'instance1', returndata=True)
    >>> code.find('plone.portlet.static') == -1
    True

    >>> code = cat('bin', 'instance2', returndata=True)
    >>> code.find('plone.portlet.static') == -1
    True

    >>> code = cat('bin', 'instance3', returndata=True)
    >>> code.find('plone.portlet.static') == -1
    True

But if the ``eggnest-src-directory`` option is not empty::

    >>> data = data.replace('eggnest-src-directory =', 'eggnest-src-directory = auto')
    >>> touch('buildout.cfg', data=data)
    >>> sh('rm src/product.txt')
    rm src/product.txt
    >>> sh('mkdir auto')
    mkdir auto
    >>> touch('auto/product.txt', data=product)
    >>> ls('auto')
    product.txt
    >>> sh('./bin/buildout -o')
    ./bin/buildout -o
    ...

and we get a zcml slug only in the specified target::

    >>> ls('parts', 'instance1', 'etc', 'package-includes')
    001-plone.portlet.static-configure.zcml

    >>> ls('parts', 'instance2', 'etc', 'package-includes')
    001-plone.portlet.static-configure.zcml

    >>> ls('parts', 'instance3', 'etc', 'package-includes')
    No directory named parts/instance3/etc/package-includes

and only the specified target's control script is updated::

    >>> code = cat('bin', 'instance1', returndata=True)
    >>> code.find('plone.portlet.static') == -1
    False

    >>> code = cat('bin', 'instance2', returndata=True)
    >>> code.find('plone.portlet.static') == -1
    False

    >>> code = cat('bin', 'instance3', returndata=True)
    >>> code.find('plone.portlet.static') == -1
    True
File Type Py Version Uploaded on Size # downloads
buildout.eggnest-0.2.tar.gz (md5) Source 2009-08-28 15:52:10.305671 7KB 77

Log in to rate this package.