Commit 067d194d authored by Jim Fulton's avatar Jim Fulton

Added support for extra paths in generated scripts.

Added an option to supply entry points directly. This is useful for
packages that don't declare their entry points.

No longer generate "py-" scripts implicitly.  Added a new option,
interpreter, to request such scripts and specifu their names.

Increased default buildout logging.
parent 91fa83b0
...@@ -29,6 +29,13 @@ python ...@@ -29,6 +29,13 @@ python
Python executable is found in the executable option of the named Python executable is found in the executable option of the named
section. section.
entry-points
A list of entry-point identifiers of the form name=module#attrs,
name is a script name, module is a module name, and a attrs is a
(possibly dotted) name of an object wihin the module. This option
is useful when working with distributions that don't declare entry
points, such as distributions not written to work with setuptools.
scripts scripts
Control which scripts are generated. The value should be a list of Control which scripts are generated. The value should be a list of
zero or more tokens. Each token is either a name, or a name zero or more tokens. Each token is either a name, or a name
...@@ -37,6 +44,10 @@ scripts ...@@ -37,6 +44,10 @@ scripts
disabled. If the option isn't given at all, then all scripts disabled. If the option isn't given at all, then all scripts
defined by the named eggs will be generated. defined by the named eggs will be generated.
interpreter
The name of a script to generate that allows access to a Python
interpreter that has the path set based on the eggs installed.
extra-paths extra-paths
Extra paths to include in a generates script. Extra paths to include in a generates script.
...@@ -69,7 +80,7 @@ install the demo package. ...@@ -69,7 +80,7 @@ install the demo package.
... index = %(server)s/index ... index = %(server)s/index
... """ % dict(server=link_server)) ... """ % dict(server=link_server))
In this example, we limited ourself to revisions before 0.3. We also In this example, we limited ourselves to revisions before 0.3. We also
specified where to find distributions using the find-links option. specified where to find distributions using the find-links option.
Let's run the buildout: Let's run the buildout:
...@@ -78,6 +89,11 @@ Let's run the buildout: ...@@ -78,6 +89,11 @@ Let's run the buildout:
>>> os.chdir(sample_buildout) >>> os.chdir(sample_buildout)
>>> buildout = os.path.join(sample_buildout, 'bin', 'buildout') >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
>>> print system(buildout), >>> print system(buildout),
buildout: Installing demo
zc.buildout.easy_install: Getting new distribution for demo<0.3
zc.buildout.easy_install: Got demo 0.2
zc.buildout.easy_install: Getting new distribution for demoneeded
zc.buildout.easy_install: Got demoneeded 1.1
Now, if we look at the buildout eggs directory: Now, if we look at the buildout eggs directory:
...@@ -93,20 +109,48 @@ link for the recipe. This egg link was actually created as part of ...@@ -93,20 +109,48 @@ link for the recipe. This egg link was actually created as part of
the sample buildout setup. Normally, when using the recipe, you'll get the sample buildout setup. Normally, when using the recipe, you'll get
a regular egg installation.) a regular egg installation.)
Script generation
-----------------
The demo egg also defined a script and we see that the script was The demo egg also defined a script and we see that the script was
installed as well: installed as well:
>>> ls(sample_buildout, 'bin') >>> ls(sample_buildout, 'bin')
- buildout - buildout
- demo - demo
- py-demo
- py-zc.buildout
Here, in addition to the buildout script, we see the demo script, Here, in addition to the buildout script, we see the demo script,
demo, and we see a script, py-demo, for giving us a Python prompt with demo.
Let's add an interpreter option:
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... parts = demo
...
... [demo]
... recipe = zc.recipe.egg
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)s/index
... interpreter = py-demo
... """ % dict(server=link_server))
>>> print system(buildout),
buildout: Uninstalling demo
buildout: Installing demo
Now we also get a py-demo script for giving us a Python prompt with
the path for demo and any eggs it depends on included in sys.path. the path for demo and any eggs it depends on included in sys.path.
This is useful for debugging and testing. This is useful for debugging and testing.
>>> ls(sample_buildout, 'bin')
- buildout
- demo
- py-demo
If we run the demo script, it prints out some minimal data: If we run the demo script, it prints out some minimal data:
>>> print system(os.path.join(sample_buildout, 'bin', 'demo')), >>> print system(os.path.join(sample_buildout, 'bin', 'demo')),
...@@ -144,6 +188,10 @@ specification. For example, We remove the restriction on demo: ...@@ -144,6 +188,10 @@ specification. For example, We remove the restriction on demo:
... """ % dict(server=link_server)) ... """ % dict(server=link_server))
>>> print system(buildout), >>> print system(buildout),
buildout: Uninstalling demo
buildout: Installing demo
zc.buildout.easy_install: Getting new distribution for demo
zc.buildout.easy_install: Got demo 0.3
Then we'll get a new demo egg: Then we'll get a new demo egg:
...@@ -162,11 +210,13 @@ The script is updated too: ...@@ -162,11 +210,13 @@ The script is updated too:
>>> print system(os.path.join(sample_buildout, 'bin', 'demo')), >>> print system(os.path.join(sample_buildout, 'bin', 'demo')),
3 1 3 1
Controlling script generation
-----------------------------
You can control which scripts get generated using the scripts option. You can control which scripts get generated using the scripts option.
For example, to suppress scripts, use the scripts option without any For example, to suppress scripts, use the scripts option without any
arguments: arguments:
>>> write(sample_buildout, 'buildout.cfg', >>> write(sample_buildout, 'buildout.cfg',
... """ ... """
... [buildout] ... [buildout]
...@@ -181,10 +231,11 @@ arguments: ...@@ -181,10 +231,11 @@ arguments:
>>> print system(buildout), >>> print system(buildout),
buildout: Uninstalling demo
buildout: Installing demo
>>> ls(sample_buildout, 'bin') >>> ls(sample_buildout, 'bin')
- buildout - buildout
- py-zc.buildout
You can also control the name used for scripts: You can also control the name used for scripts:
...@@ -201,11 +252,15 @@ You can also control the name used for scripts: ...@@ -201,11 +252,15 @@ You can also control the name used for scripts:
... """ % dict(server=link_server)) ... """ % dict(server=link_server))
>>> print system(buildout), >>> print system(buildout),
buildout: Uninstalling demo
buildout: Installing demo
>>> ls(sample_buildout, 'bin') >>> ls(sample_buildout, 'bin')
- buildout - buildout
- foo - foo
- py-zc.buildout
Specifying extra script paths
-----------------------------
If we need to include extra paths in a script, we can use the If we need to include extra paths in a script, we can use the
extra-paths option: extra-paths option:
...@@ -226,6 +281,8 @@ extra-paths option: ...@@ -226,6 +281,8 @@ extra-paths option:
... """ % dict(server=link_server)) ... """ % dict(server=link_server))
>>> print system(buildout), >>> print system(buildout),
buildout: Uninstalling demo
buildout: Installing demo
Let's look at the script that was generated: Let's look at the script that was generated:
...@@ -237,7 +294,7 @@ Let's look at the script that was generated: ...@@ -237,7 +294,7 @@ Let's look at the script that was generated:
'/tmp/xyzsample-install/demo-0.3-py2.3.egg', '/tmp/xyzsample-install/demo-0.3-py2.3.egg',
'/tmp/xyzsample-install/demoneeded-1.1-py2.3.egg', '/tmp/xyzsample-install/demoneeded-1.1-py2.3.egg',
'/foo/bar', '/foo/bar',
'/spam/eggs' '/spam/eggs',
] ]
<BLANKLINE> <BLANKLINE>
import eggrecipedemo import eggrecipedemo
...@@ -245,8 +302,54 @@ Let's look at the script that was generated: ...@@ -245,8 +302,54 @@ Let's look at the script that was generated:
if __name__ == '__main__': if __name__ == '__main__':
eggrecipedemo.main() eggrecipedemo.main()
Specifying entry points
-----------------------
Scripts can be generated for entry points declared explcitly. We can
declate entry points using the entry-points option:
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... parts = demo
...
... [demo]
... recipe = zc.recipe.egg
... find-links = %(server)s
... index = %(server)s/index
... extra-paths =
... /foo/bar
... /spam/eggs
... entry-points = alt=eggrecipedemo:alt other=foo.bar:a.b.c
... """ % dict(server=link_server))
>>> print system(buildout),
buildout: Uninstalling demo
buildout: Installing demo
>>> ls(sample_buildout, 'bin')
- alt
- buildout
- demo
- other
>>> cat(sample_buildout, 'bin', 'other')
#!/usr/local/bin/python2.3
<BLANKLINE>
import sys
sys.path[0:0] = [
'/private/tmp/tmp88gKbfsample-buildout/eggs/demo-0.3-py2.3.egg',
'/private/tmp/tmp88gKbfsample-buildout/eggs/demoneeded-1.1-py2.3.egg',
'/foo/bar',
'/spam/eggs',
]
<BLANKLINE>
import foo.bar
<BLANKLINE>
if __name__ == '__main__':
foo.bar.a.b.c()
Offline mode Offline mode
------------ ------------
...@@ -267,3 +370,5 @@ be made to contact an index server: ...@@ -267,3 +370,5 @@ be made to contact an index server:
... """ % dict(server=link_server)) ... """ % dict(server=link_server))
>>> print system(buildout), >>> print system(buildout),
buildout: Uninstalling demo
buildout: Installing demo
...@@ -6,10 +6,10 @@ and generate scripts based on the resulting working sets. The egg ...@@ -6,10 +6,10 @@ and generate scripts based on the resulting working sets. The egg
recipe provides an API that other recipes can use. recipe provides an API that other recipes can use.
A recipe can reuse the egg recipe, supporting the eggs, find-links, A recipe can reuse the egg recipe, supporting the eggs, find-links,
index, and python options. This is done by creating an egg recipe index, extra-paths, and python options. This is done by creating an
instance in a recipes's contructor. In the recipe's install script, egg recipe instance in a recipes's contructor. In the recipe's
the egg-recipe instance's working_set method is used to collect the install script, the egg-recipe instance's working_set method is used
requested eggs and working set. to collect the requested eggs and working set.
To illustrate, we create a sample recipe that is a very thin layer To illustrate, we create a sample recipe that is a very thin layer
around the egg recipe: around the egg recipe:
...@@ -37,6 +37,7 @@ around the egg recipe: ...@@ -37,6 +37,7 @@ around the egg recipe:
... print 'Working set:' ... print 'Working set:'
... for d in ws: ... for d in ws:
... print d ... print d
... print 'extra paths:', self.egg.extra_paths
... """) ... """)
Here we instantiated the egg recipe in the constructor, saving it in Here we instantiated the egg recipe in the constructor, saving it in
...@@ -77,7 +78,7 @@ of extra requirements to be included in the working set. ...@@ -77,7 +78,7 @@ of extra requirements to be included in the working set.
>>> import os >>> import os
>>> os.chdir(sample_buildout) >>> os.chdir(sample_buildout)
>>> buildout = os.path.join(sample_buildout, 'bin', 'buildout') >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
>>> print system(buildout), >>> print system(buildout + ' -q'),
Part: sample-part Part: sample-part
Egg requirements: Egg requirements:
demo<0.3 demo<0.3
...@@ -85,6 +86,7 @@ of extra requirements to be included in the working set. ...@@ -85,6 +86,7 @@ of extra requirements to be included in the working set.
demo 0.2 demo 0.2
other 1.0 other 1.0
demoneeded 1.1 demoneeded 1.1
extra paths: []
We can see that the options were augmented with additionl data We can see that the options were augmented with additionl data
computed by the egg recipe by looking at .installed.cfg: computed by the egg recipe by looking at .installed.cfg:
...@@ -108,3 +110,35 @@ computed by the egg recipe by looking at .installed.cfg: ...@@ -108,3 +110,35 @@ computed by the egg recipe by looking at .installed.cfg:
find-links = http://localhost:27071/ find-links = http://localhost:27071/
index = http://localhost:27071/index index = http://localhost:27071/index
recipe = sample recipe = sample
If we use the extra-paths option:
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... develop = sample
... parts = sample-part
...
... [sample-part]
... recipe = sample
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)sindex
... extras = other
... extra-paths = /foo/bar
... /spam/eggs
... """ % dict(server=link_server))
Then we'll see that reflected in the extra_paths attribute in the egg
recipe instance:
>>> print system(buildout + ' -q'),
Part: sample-part
Egg requirements:
demo<0.3
Working set:
demo 0.2
other 1.0
demoneeded 1.1
extra paths: ['/foo/bar', '/spam/eggs']
...@@ -95,6 +95,7 @@ the egg: ...@@ -95,6 +95,7 @@ the egg:
>>> buildout = os.path.join(sample_buildout, 'bin', 'buildout') >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
>>> print system(buildout), >>> print system(buildout),
buildout: Installing extdemo
zip_safe flag not set; analyzing archive contents... zip_safe flag not set; analyzing archive contents...
We got the zip_safe warning because the source distribution we used We got the zip_safe warning because the source distribution we used
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
$Id$ $Id$
""" """
import os, re, zipfile import logging, os, re, zipfile
import zc.buildout.easy_install import zc.buildout.easy_install
class Egg: class Egg:
...@@ -87,8 +87,11 @@ class Egg: ...@@ -87,8 +87,11 @@ class Egg:
return orig_distributions, ws return orig_distributions, ws
parse_entry_point = re.compile(
'([^=]+)=(\w+(?:[.]\w+)*):(\w+(?:[.]\w+)*)$'
).match
def install(self): def install(self):
distributions, ws = self.working_set() reqs, ws = self.working_set()
options = self.options options = self.options
scripts = options.get('scripts') scripts = options.get('scripts')
...@@ -99,9 +102,20 @@ class Egg: ...@@ -99,9 +102,20 @@ class Egg:
('=' in s) and s.split('=', 1) or (s, s) ('=' in s) and s.split('=', 1) or (s, s)
for s in scripts for s in scripts
]) ])
for s in options.get('entry-points', '').split():
parsed = self.parse_entry_point(s)
if not parsed:
logging.getLogger(self.name).error(
"Cannot parse the entry point %s.", s)
raise zc.buildout.UserError("Invalid entry point")
reqs.append(parsed.groups())
return zc.buildout.easy_install.scripts( return zc.buildout.easy_install.scripts(
distributions, ws, options['executable'], reqs, ws, options['executable'],
options['_b'], options['_b'],
scripts=scripts, scripts=scripts,
extra_paths=self.extra_paths) extra_paths=self.extra_paths,
interpreter=options.get('interpreter'),
)
...@@ -46,6 +46,7 @@ install the demo package using Python 2.3. ...@@ -46,6 +46,7 @@ install the demo package using Python 2.3.
... find-links = %(server)s ... find-links = %(server)s
... index = %(server)s/index ... index = %(server)s/index
... python = python2.3 ... python = python2.3
... interpreter = py-demo
... """ % dict(server=link_server, python23=python2_3_executable)) ... """ % dict(server=link_server, python23=python2_3_executable))
Now, if we run the buildout: Now, if we run the buildout:
...@@ -54,6 +55,11 @@ Now, if we run the buildout: ...@@ -54,6 +55,11 @@ Now, if we run the buildout:
>>> os.chdir(sample_buildout) >>> os.chdir(sample_buildout)
>>> buildout = os.path.join(sample_buildout, 'bin', 'buildout') >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
>>> print system(buildout), >>> print system(buildout),
buildout: Installing demo
zc.buildout.easy_install: Getting new distribution for demo<0.3
zc.buildout.easy_install: Got demo 0.2
zc.buildout.easy_install: Getting new distribution for demoneeded
zc.buildout.easy_install: Got demoneeded 1.1
we'll get the Python 2.3 eggs for demo and demoneeded: we'll get the Python 2.3 eggs for demo and demoneeded:
...@@ -78,7 +84,7 @@ And the generated scripts invoke Python 2.3: ...@@ -78,7 +84,7 @@ And the generated scripts invoke Python 2.3:
import sys import sys
sys.path[0:0] = [ sys.path[0:0] = [
'/private/tmp/tmpOEtRO8sample-buildout/eggs/demo-0.2-py2.3.egg', '/private/tmp/tmpOEtRO8sample-buildout/eggs/demo-0.2-py2.3.egg',
'/private/tmp/tmpOEtRO8sample-buildout/eggs/demoneeded-1.1-py2.3.egg' '/private/tmp/tmpOEtRO8sample-buildout/eggs/demoneeded-1.1-py2.3.egg',
] ]
<BLANKLINE> <BLANKLINE>
import eggrecipedemo import eggrecipedemo
...@@ -97,7 +103,7 @@ And the generated scripts invoke Python 2.3: ...@@ -97,7 +103,7 @@ And the generated scripts invoke Python 2.3:
<BLANKLINE> <BLANKLINE>
sys.path[0:0] = [ sys.path[0:0] = [
'/tmp/tmp5zS2Afsample-buildout/eggs/demo-0.2-py2.3.egg', '/tmp/tmp5zS2Afsample-buildout/eggs/demo-0.2-py2.3.egg',
'/tmp/tmp5zS2Afsample-buildout/eggs/demoneeded-1.1-py2.3.egg' '/tmp/tmp5zS2Afsample-buildout/eggs/demoneeded-1.1-py2.3.egg',
] ]
<BLANKLINE> <BLANKLINE>
_interactive = True _interactive = True
...@@ -135,6 +141,7 @@ If we change the Python version to 2.4, we'll use Python 2.4 eggs: ...@@ -135,6 +141,7 @@ If we change the Python version to 2.4, we'll use Python 2.4 eggs:
... find-links = %(server)s ... find-links = %(server)s
... index = %(server)s/index ... index = %(server)s/index
... python = python2.4 ... python = python2.4
... interpreter = py-demo
... ...
... [python2.4] ... [python2.4]
... executable = %(python24)s ... executable = %(python24)s
...@@ -142,6 +149,12 @@ If we change the Python version to 2.4, we'll use Python 2.4 eggs: ...@@ -142,6 +149,12 @@ If we change the Python version to 2.4, we'll use Python 2.4 eggs:
... """ % dict(server=link_server, python24=python2_4_executable)) ... """ % dict(server=link_server, python24=python2_4_executable))
>>> print system(buildout), >>> print system(buildout),
buildout: Uninstalling demo
buildout: Installing demo
zc.buildout.easy_install: Getting new distribution for demo<0.3
zc.buildout.easy_install: Got demo 0.2
zc.buildout.easy_install: Getting new distribution for demoneeded
zc.buildout.easy_install: Got demoneeded 1.1
>>> ls(sample_buildout, 'eggs') >>> ls(sample_buildout, 'eggs')
- demo-0.2-py2.3.egg - demo-0.2-py2.3.egg
...@@ -162,7 +175,7 @@ If we change the Python version to 2.4, we'll use Python 2.4 eggs: ...@@ -162,7 +175,7 @@ If we change the Python version to 2.4, we'll use Python 2.4 eggs:
import sys import sys
sys.path[0:0] = [ sys.path[0:0] = [
'/private/tmp/tmpOEtRO8sample-buildout/eggs/demo-0.2-py2.4.egg', '/private/tmp/tmpOEtRO8sample-buildout/eggs/demo-0.2-py2.4.egg',
'/private/tmp/tmpOEtRO8sample-buildout/eggs/demoneeded-1.1-py2.4.egg' '/private/tmp/tmpOEtRO8sample-buildout/eggs/demoneeded-1.1-py2.4.egg',
] ]
<BLANKLINE> <BLANKLINE>
import eggrecipedemo import eggrecipedemo
...@@ -183,7 +196,7 @@ If we change the Python version to 2.4, we'll use Python 2.4 eggs: ...@@ -183,7 +196,7 @@ If we change the Python version to 2.4, we'll use Python 2.4 eggs:
<BLANKLINE> <BLANKLINE>
sys.path[0:0] = [ sys.path[0:0] = [
'/tmp/tmp5zS2Afsample-buildout/eggs/demo-0.2-py2.4.egg', '/tmp/tmp5zS2Afsample-buildout/eggs/demo-0.2-py2.4.egg',
'/tmp/tmp5zS2Afsample-buildout/eggs/demoneeded-1.1-py2.4.egg' '/tmp/tmp5zS2Afsample-buildout/eggs/demoneeded-1.1-py2.4.egg',
] ]
<BLANKLINE> <BLANKLINE>
_interactive = True _interactive = True
......
...@@ -122,7 +122,7 @@ def test_suite(): ...@@ -122,7 +122,7 @@ def test_suite():
setUp=setUpCustom, tearDown=zc.buildout.testing.buildoutTearDown, setUp=setUpCustom, tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([ checker=renormalizing.RENormalizing([
(re.compile("(d ((ext)?demo(needed)?|other)" (re.compile("(d ((ext)?demo(needed)?|other)"
"-\d[.]\d-py)\d[.]\d(-[^. \t\n]+)?[.]egg"), "-\d[.]\d-py)\d[.]\d(-\S+)?[.]egg"),
'\\1V.V.egg'), '\\1V.V.egg'),
(re.compile('extdemo.c\n.+\\extdemo.exp\n'), ''), (re.compile('extdemo.c\n.+\\extdemo.exp\n'), ''),
]), ]),
......
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