Commit de3a246c authored by Jim Fulton's avatar Jim Fulton

Refactored the way recipes are run and how they should be written.

If a recipe uses any data from other sections, the recipe needs to
update it's data when the recipe is constructed.

Need more discussion of this in the docs.
parent 6a114131
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
$Id$ $Id$
""" """
import os
import zc.buildout.egglinker import zc.buildout.egglinker
import zc.buildout.easy_install import zc.buildout.easy_install
...@@ -25,26 +26,27 @@ class Egg: ...@@ -25,26 +26,27 @@ class Egg:
self.buildout = buildout self.buildout = buildout
self.name = name self.name = name
self.options = options self.options = options
links = options.get('find-links',
def install(self): buildout['buildout'].get('find-links'))
distribution = self.options.get('distribution', self.name)
links = self.options.get(
'find-links',
self.buildout['buildout'].get('find-links'),
)
if links: if links:
links = links.split() buildout_directory = buildout['buildout']['directory']
links = [os.path.join(buildout_directory, link)
for link in links.split()]
options['find-links'] = '\n'.join(links)
else: else:
links = () links = ()
self.links = links
buildout = self.buildout options['_b'] = buildout['buildout']['bin-directory']
options['_e'] = buildout['buildout']['eggs-directory']
def install(self):
options = self.options
distribution = options.get('distribution', self.name)
zc.buildout.easy_install.install( zc.buildout.easy_install.install(
distribution, distribution, options['_e'], self.links)
buildout.eggs,
[buildout.buildout_path(link) for link in links],
)
scripts = self.options.get('scripts') scripts = options.get('scripts')
if scripts or scripts is None: if scripts or scripts is None:
if scripts is not None: if scripts is not None:
scripts = scripts.split() scripts = scripts.split()
...@@ -53,6 +55,6 @@ class Egg: ...@@ -53,6 +55,6 @@ class Egg:
for s in scripts for s in scripts
]) ])
return zc.buildout.egglinker.scripts( return zc.buildout.egglinker.scripts(
[distribution], buildout.bin, [buildout.eggs], [distribution],
scripts=scripts) options['_b'], [options['_e']], scripts=scripts)
This diff is collapsed.
...@@ -92,9 +92,13 @@ and then we'll create a source file for our mkdir recipe: ...@@ -92,9 +92,13 @@ and then we'll create a source file for our mkdir recipe:
... self.buildout = buildout ... self.buildout = buildout
... self.name = name ... self.name = name
... self.options = options ... self.options = options
... options['path'] = os.path.join(
... buildout['buildout']['directory'],
... options['path'],
... )
... ...
... def install(self): ... def install(self):
... path = self.buildout.buildout_path(self.options['path']) ... path = self.options['path']
... if not os.path.isdir(path): ... if not os.path.isdir(path):
... print 'Creating directory', os.path.basename(path) ... print 'Creating directory', os.path.basename(path)
... os.mkdir(path) ... os.mkdir(path)
...@@ -104,14 +108,21 @@ and then we'll create a source file for our mkdir recipe: ...@@ -104,14 +108,21 @@ and then we'll create a source file for our mkdir recipe:
The recipe defines a constructor that takes a buildout object, a part The recipe defines a constructor that takes a buildout object, a part
name, and an options dictionary. It saves them in instance attributes. name, and an options dictionary. It saves them in instance attributes.
If the path is relative, we'll interpret it as relative to the
buildout directory. The buildout object passed in is a mapping from
section name to a mapping of options for that section. The buildout
directory is available as the directory option of the buildout
section. We normalize the path and save it back into the options
directory.
**IMPORTANT**: Any time we use data from another section, it is important
to reflect that data in the recipe options, as this data is used to
decide if a part configuration has changed and a part needs to be
reinstalled.
The install method is responsible for creating the part. In this The install method is responsible for creating the part. In this
case, we need the path of the directory to create. We'll use a case, we need the path of the directory to create. We'll use a
buildout option from our options dictionary. If the path is relative, path option from our options dictionary.
we'll interpret it relative to the buildout directory. The buildout
buildout_path method gives us a path relative to the buildout. It
uses os.path.join, so if we pass it an absolute path, we'll get the
absolute path back. (If no arguments are passed to base_path, then the
buildout directory is returned.)
We made the method chatty so that we can observe what it's doing. We made the method chatty so that we can observe what it's doing.
...@@ -134,14 +145,13 @@ installed as an egg. We need to define a setup script for this: ...@@ -134,14 +145,13 @@ installed as an egg. We need to define a setup script for this:
... ) ... )
... """) ... """)
Here we've defined a package containing just our module. We've also Here we've defined a package with an entry_point. Entry points provide
defined an entry point. Entry points provide a way for an egg to a way for an egg to define the services it provides. Here we've said
define the services it provides. Here we've said that we define a that we define a zc.buildout entry point named default. Recipe
zc.buildout entry point named default. Recipe classes must be exposed classes must be exposed as entry points in the zc.buildout group. we
as entry points in the zc.buildout group. we give entry points names give entry points names within the group. The name "default" is
within the group. The name "default" is somewhat special because it somewhat special because it allows a recipe to be referenced using a
allows a recipe to be referenced using a package name without naming package name without naming an entry point.
an entry point.
We also need a README.txt for our recipes to avoid a warning: We also need a README.txt for our recipes to avoid a warning:
...@@ -219,12 +229,14 @@ installed: ...@@ -219,12 +229,14 @@ installed:
parts = data_dir parts = data_dir
<BLANKLINE> <BLANKLINE>
[data_dir] [data_dir]
__buildout_installed__ = mystuff __buildout_installed__ = /tmp/sample-buildout/mystuff
__buildout_signature__ = recipes-O3ypTgKOkHMqMwKvMfvHnA== __buildout_signature__ = recipes-c7vHV6ekIDUPy/7fjAaYjg==
path = mystuff path = /tmp/sample-buildout/mystuff
recipe = recipes:mkdir recipe = recipes:mkdir
Note that the directory we installed is included in .installed.cfg. Note that the directory we installed is included in .installed.cfg.
In addition, the path option includes the actual destination
directory.
If we change the name of the directory in the configuration file, If we change the name of the directory in the configuration file,
we'll see that the directory gets removed and recreated: we'll see that the directory gets removed and recreated:
...@@ -639,27 +651,27 @@ configuration and run the buildout in the usual way: ...@@ -639,27 +651,27 @@ configuration and run the buildout in the usual way:
<BLANKLINE> <BLANKLINE>
[debug] [debug]
__buildout_installed__ = __buildout_installed__ =
__buildout_signature__ = recipes-IX/o5hMSw90MtZVxRpjz0Q== __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
op1 = 1 op1 = 1
op7 = 7 op7 = 7
recipe = recipes:debug recipe = recipes:debug
<BLANKLINE> <BLANKLINE>
[d1] [d1]
__buildout_installed__ = d1 __buildout_installed__ = /tmp/sample-buildout/d1
__buildout_signature__ = recipes-IX/o5hMSw90MtZVxRpjz0Q== __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
path = d1 path = /tmp/sample-buildout/d1
recipe = recipes:mkdir recipe = recipes:mkdir
<BLANKLINE> <BLANKLINE>
[d2] [d2]
__buildout_installed__ = d2 __buildout_installed__ = /tmp/sample-buildout/d2
__buildout_signature__ = recipes-IX/o5hMSw90MtZVxRpjz0Q== __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
path = d2 path = /tmp/sample-buildout/d2
recipe = recipes:mkdir recipe = recipes:mkdir
<BLANKLINE> <BLANKLINE>
[d3] [d3]
__buildout_installed__ = d3 __buildout_installed__ = /tmp/sample-buildout/d3
__buildout_signature__ = recipes-IX/o5hMSw90MtZVxRpjz0Q== __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
path = d3 path = /tmp/sample-buildout/d3
recipe = recipes:mkdir recipe = recipes:mkdir
Now we'll update our configuration file: Now we'll update our configuration file:
...@@ -721,33 +733,33 @@ The .installed.cfg is only updated for the recipes that ran: ...@@ -721,33 +733,33 @@ The .installed.cfg is only updated for the recipes that ran:
<BLANKLINE> <BLANKLINE>
[debug] [debug]
__buildout_installed__ = __buildout_installed__ =
__buildout_signature__ = recipes-IX/o5hMSw90MtZVxRpjz0Q== __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
op1 = 1 op1 = 1
op7 = 7 op7 = 7
recipe = recipes:debug recipe = recipes:debug
<BLANKLINE> <BLANKLINE>
[d2] [d2]
__buildout_installed__ = d2 __buildout_installed__ = /tmp/sample-buildout/d2
__buildout_signature__ = recipes-IX/o5hMSw90MtZVxRpjz0Q== __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
path = d2 path = /tmp/sample-buildout/d2
recipe = recipes:mkdir recipe = recipes:mkdir
<BLANKLINE> <BLANKLINE>
[d3] [d3]
__buildout_installed__ = data3 __buildout_installed__ = /tmp/sample-buildout/data3
__buildout_signature__ = recipes-IX/o5hMSw90MtZVxRpjz0Q== __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
path = data3 path = /tmp/sample-buildout/data3
recipe = recipes:mkdir recipe = recipes:mkdir
<BLANKLINE> <BLANKLINE>
[d4] [d4]
__buildout_installed__ = data4 __buildout_installed__ = /tmp/sample-buildout/data4
__buildout_signature__ = recipes-IX/o5hMSw90MtZVxRpjz0Q== __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
path = data4 path = /tmp/sample-buildout/data4
recipe = recipes:mkdir recipe = recipes:mkdir
<BLANKLINE> <BLANKLINE>
[d1] [d1]
__buildout_installed__ = d1 __buildout_installed__ = /tmp/sample-buildout/d1
__buildout_signature__ = recipes-IX/o5hMSw90MtZVxRpjz0Q== __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
path = d1 path = /tmp/sample-buildout/d1
recipe = recipes:mkdir recipe = recipes:mkdir
Note that the installed data for debug, d1, and d2 haven't changed, Note that the installed data for debug, d1, and d2 haven't changed,
......
...@@ -53,7 +53,7 @@ def system(command, input=''): ...@@ -53,7 +53,7 @@ def system(command, input=''):
return o.read() return o.read()
def buildoutSetUp(test): def buildoutSetUp(test):
sample = tempfile.mkdtemp('buildout-tests') sample = tempfile.mkdtemp('sample-buildout')
for name in ('bin', 'eggs', 'parts'): for name in ('bin', 'eggs', 'parts'):
os.mkdir(os.path.join(sample, name)) os.mkdir(os.path.join(sample, name))
...@@ -118,7 +118,7 @@ def runsetup(d): ...@@ -118,7 +118,7 @@ def runsetup(d):
os.chdir(here) os.chdir(here)
def create_sample_eggs(test): def create_sample_eggs(test):
sample = tempfile.mkdtemp('eggtest') sample = tempfile.mkdtemp('sample-eggs')
test.globs['_sample_eggs_container'] = sample test.globs['_sample_eggs_container'] = sample
test.globs['sample_eggs'] = os.path.join(sample, 'dist') test.globs['sample_eggs'] = os.path.join(sample, 'dist')
write(sample, 'README.txt', '') write(sample, 'README.txt', '')
......
...@@ -94,7 +94,9 @@ def test_suite(): ...@@ -94,7 +94,9 @@ def test_suite():
checker=renormalizing.RENormalizing([ checker=renormalizing.RENormalizing([
(re.compile('__buildout_signature__ = recipes-\S+'), (re.compile('__buildout_signature__ = recipes-\S+'),
'__buildout_signature__ = recipes-SSSSSSSSSSS'), '__buildout_signature__ = recipes-SSSSSSSSSSS'),
]) (re.compile('\S+sample-(\w+)%s(\S+)' % os.path.sep),
r'/sample-\1/\2'),
])
), ),
doctest.DocFileSuite( doctest.DocFileSuite(
'egglinker.txt', 'easy_install.txt', 'egglinker.txt', 'easy_install.txt',
......
...@@ -25,6 +25,11 @@ class TestRunner: ...@@ -25,6 +25,11 @@ class TestRunner:
self.buildout = buildout self.buildout = buildout
self.name = name self.name = name
self.options = options self.options = options
options['script'] = os.path.join(buildout['buildout']['bin-directory'],
options.get('script', self.name),
)
options['_e'] = buildout['buildout']['eggs-directory']
def install(self): def install(self):
distributions = [ distributions = [
...@@ -34,13 +39,12 @@ class TestRunner: ...@@ -34,13 +39,12 @@ class TestRunner:
] ]
path = zc.buildout.egglinker.path( path = zc.buildout.egglinker.path(
distributions+['zope.testing'], distributions+['zope.testing'],
[self.buildout.eggs], [self.options['_e']],
) )
locations = [zc.buildout.egglinker.location(distribution, locations = [zc.buildout.egglinker.location(distribution,
[self.buildout.eggs]) [self.options['_e']])
for distribution in distributions] for distribution in distributions]
script = self.options.get('script', self.name) script = self.options['script']
script = self.buildout.buildout_path('bin', script)
open(script, 'w').write(tests_template % dict( open(script, 'w').write(tests_template % dict(
PYTHON=sys.executable, PYTHON=sys.executable,
PATH="',\n '".join(path), PATH="',\n '".join(path),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment