Dependencies and zc.buildout
... or how dependency resolution actually works ...
In zc.buildout we have the parts. Those are put together using the 'parts =' parameter in buildouts main section.
At some point you may got the feeling this defines the parts order of execution. But this is most time wrong. It just defines which parts to take into account. The order given there is only important if there don't occur any reordering later.
This means order is valid for:
[buildout] parts = part1 part2 [part1] recipe = somerecipe [part2] recipe = somerecipe
But dependencies can overrule the given order, like:
[buildout]
parts = part1 part2
[part1]
recipe = somerecipe1
someparameter = ${part2:otherparameter}
[part2]
recipe = somerecipe2
otherparameter = foo
part2 got executed first, then part1.
Now its not necessary to references part2 anymore in parts, the following is exact the same as above example:
[buildout]
parts = part1
[part1]
recipe = somerecipe
someparameter = ${part2:otherparameter}
[part2]
recipe = somerecipe
otherparameter = foo
With this knowledge we can simplify our recent Plone 3.2 buildouts, well even if this is not a major advantage, its just removes redundant information. But lets demonstrate:
[buildout]
parts = instance
extends = http://dist.plone.org/release/3.2rc1/versions.cfg
versions = versions
newest = false
find-links =
http://dist.plone.org
http://download.zope.org/ppix/
http://download.zope.org/distribution/
http://effbot.org/downloads
[zope2]
recipe = plone.recipe.zope2install
url = http://www.zope.org/Products/Zope/2.10.7/Zope-2.10.7-final.tgz
fake-zope-eggs = true
additional-fake-eggs =
ZConfig
pytz
[instance]
recipe = plone.recipe.zope2instance
user = admin:admin
http-address = 8080
zope2-location = ${zope2:location}
eggs = Plone
At the moment it is common to declare eggs always in the buildout section (same for zcml). I switched to declare them always in the instance section. If I have more than one instance I reference the eggs, zcml and products section of the first instance in the following. Major reason is to have better control over the order in which eggs are built/fetched. I hit a problem while trying to use celementree. The provided binary egg does not work correctly (no idea why). Fortunately we can do custom builds and it just works to do:
[celementtree] recipe = zc.recipe.egg:custom egg = celementtree
If all eggs, specifically the add-on which depends on celementree, is declared in the buildouts eggs section it is fetched first, buildout fails.
Declaring all eggs in the instances eggs section, except the special one helps:
[buildout]
parts = instance
# ... missing lines see above
eggs =
${celementtree:egg}
[celementtree]
recipe = zc.recipe.egg:custom
egg = celementtree
# ... missing lines see above
[instance]
# ... missing lines see above
eggs =
${buildout:eggs}
Plone
my.addon.dependend_on_celementree
Now buildout first resolves dependencies of the main [buildout] section and first [celementree] is built. Next [instance] ist hit, but it depends on [zope], so first zope is built, then [instance] and at the moment it builds it resolves the eggs with it dependencies, celementree is already there so it does not need to fetch it again.
I hope this make things a bit more clear.
