Index: src/zc/buildout/tests.py =================================================================== --- src/zc/buildout/tests.py (revision 123353) +++ src/zc/buildout/tests.py (working copy) @@ -1309,6 +1309,103 @@ """ +def recipe_extras(): + """ + +The buildout will check for extra requirements of recipes. + +Let's create a recipe egg + + >>> mkdir('recipe') + >>> write('recipe', 'recipe.py', + ... ''' + ... class Recipe: + ... def __init__(*a): pass + ... def install(self): + ... return () + ... update = install + ... ''') + + >>> write('recipe', 'setup.py', + ... ''' + ... from setuptools import setup + ... setup(name='recipe', version='1', py_modules=['recipe'], + ... entry_points={'zc.buildout': ['default = recipe:Recipe', + ... 'ext = recipe:Recipe [extra]'],}, + ... extras_require={'extra': ['extra']} + ... ) + ... ''') + + >>> write('recipe', 'README', '') + + >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS + Running setup script 'recipe/setup.py'. + ... + + >>> rmdir('recipe', 'build') + +And an optional extra requirement + + >>> mkdir('extra') + >>> write('extra', 'recipe.py', + ... ''' + ... class Dummy: + ... pass + ... ''') + + >>> write('extra', 'setup.py', + ... ''' + ... from setuptools import setup + ... setup(name='extra', version='1', py_modules=['recipe'], + ... ) + ... ''') + + >>> write('extra', 'README', '') + + >>> print system(buildout+' setup extra bdist_egg'), # doctest: +ELLIPSIS + Running setup script 'extra/setup.py'. + ... + + >>> rmdir('extra', 'build') + +And update our buildout to use it. + + >>> write('buildout.cfg', + ... ''' + ... [buildout] + ... parts = foo + ... find-links = %s + ... %s + ... + ... [foo] + ... recipe = recipe + ... ''' % (join('recipe', 'dist'), join('extra', 'dist'))) + + >>> print system(buildout), + Getting distribution for 'recipe'. + Got recipe 1. + Installing foo. + +Now let's change our requirement + + >>> write('buildout.cfg', + ... ''' + ... [buildout] + ... parts = foo + ... find-links = %s + ... %s + ... + ... [foo] + ... recipe = recipe[extra]:ext + ... ''' % (join('recipe', 'dist'), join('extra', 'dist'))) + + >>> print system(buildout), + Getting distribution for 'extra'. + Got extra 1. + Uninstalling foo. + Installing foo. +""" + def update_adds_to_uninstall_list(): """ Index: src/zc/buildout/buildout.py =================================================================== --- src/zc/buildout/buildout.py (revision 123353) +++ src/zc/buildout/buildout.py (working copy) @@ -1103,9 +1103,15 @@ __doing__ = 'Loading recipe %r.', spec try: req = pkg_resources.Requirement.parse(spec) + dist = pkg_resources.working_set.find(req) + missing_extras = True + if dist: + missing_extras = None in \ + [pkg_resources.working_set.find(r) + for r in dist.requires(req.extras)] buildout_options = buildout['buildout'] - if pkg_resources.working_set.find(req) is None: + if dist is None or missing_extras: __doing__ = 'Installing recipe %s.', spec if buildout.offline: dest = None