Commit 6107db1f authored by Gary Poster's avatar Gary Poster

A -S branch

parents 337b7586 a542e58e
...@@ -6,34 +6,6 @@ Change History ...@@ -6,34 +6,6 @@ Change History
New Features: New Features:
- Buildout can be safely used with a system Python. Note that Python is
always used, by default, with -S: that is, site-packages are not
included. If you would like to have access to your site-packages, see
the next bullet point.
A limitation: in no cases are distributions in your site-packages used
to satisfy buildout dependencies. The site-packages can be used in
addition to the dependencies specified in your buildout, and buildout
dependencies can override code in your site-packages, but even if your
Python's site-packages has the same exact version as specified in your
buildout configuration, buildout will still use its own copy.
- Added new function, ``zc.buildout.easy_install.generate_scripts``, to
generate scripts and interpreter. It produces a full-featured
interpreter (all command-line options supported) and the ability to
safely let scripts include site packages. A safe and functional
site.py also is available, which will make it safer for use with a
system Python than the pre-existing buildout function
(``zc.buildout.easy_install.scripts``) and recipe (``zc.recipe.egg``).
End users should see z3c.recipe.scripts, which provides this
functionality within buildout configuration files.
The older function (``zc.buildout.easy_install.scripts``) and recipe
(``zc.recipe.egg``) still survive, because of their comparative attractive
simplicity, because they still work well when a non-system Python is used,
and because they can often be used well with a system Python.
- Improve bootstrap. - Improve bootstrap.
* New options let you specify where to find ez_setup.py and where to find * New options let you specify where to find ez_setup.py and where to find
...@@ -47,24 +19,40 @@ New Features: ...@@ -47,24 +19,40 @@ New Features:
Bugs fixed: Bugs fixed:
- Incrementing didn't work properly when extending multiple files.
https://bugs.launchpad.net/zc.buildout/+bug/421022
- The download API computed MD5 checksums of text files wrong on Windows.
- The handling and documenting of default buildout options was normalized. - The handling and documenting of default buildout options was normalized.
This means, among other things, that ``bin/buildout -vv`` and This means, among other things, that ``bin/buildout -vv`` and
``bin/buildout annotate`` correctly list more of the options. ``bin/buildout annotate`` correctly list more of the options.
- Installing a namespace package using a Python that already has a package 1.4.3 (2009-12-10)
in the same namespace (e.g., in the Python's site-packages) in some cases. ==================
Bugs fixed:
- The error showed itself when at least two dependencies were in a shared - Using pre-detected setuptools version for easy_installing tgz files. This
location like site-packages, and the first one met the "versions" prevents a recursion error when easy_installing an upgraded "distribute"
setting. The first dependency would be added, but subsequent tgz. Note that setuptools did not have this recursion problem solely
dependencies from the same location (e.g., site-packages) would use because it was packaged as an ``.egg``, which does not have to go through
the version of the package found in the shared location, ignoring the the easy_install step.
version setting.
1.4.2 (2009-11-01)
==================
New Feature:
- Added a --distribute option to the bootstrap script, in order
to use Distribute rather than Setuptools. By default, Setuptools
is used.
Bugs fixed:
- While checking for new versions of setuptools and buildout itself,
compare requirement locations instead of requirement objects.
- Incrementing didn't work properly when extending multiple files.
https://bugs.launchpad.net/zc.buildout/+bug/421022
- The download API computed MD5 checksums of text files wrong on Windows.
1.4.1 (2009-08-27) 1.4.1 (2009-08-27)
================== ==================
......
...@@ -37,11 +37,6 @@ Existing recipes include: ...@@ -37,11 +37,6 @@ Existing recipes include:
dependencies. It installs their console-script entry points with dependencies. It installs their console-script entry points with
the needed eggs included in their paths. the needed eggs included in their paths.
`z3c.recipe.scripts <http://pypi.python.org/pypi/z3c.recipe.scripts>`_
This scripts recipe builds interpreter scripts and entry point scripts
based on eggs. These scripts have more features and flexibility than the
ones offered by zc.recipe.egg.
`zc.recipe.testrunner <http://pypi.python.org/pypi/zc.recipe.testrunner>`_ `zc.recipe.testrunner <http://pypi.python.org/pypi/zc.recipe.testrunner>`_
The testrunner egg creates a test runner script for one or The testrunner egg creates a test runner script for one or
more eggs. more eggs.
...@@ -131,7 +126,7 @@ If I need to run a previous version of zc.buildout, I use the ...@@ -131,7 +126,7 @@ If I need to run a previous version of zc.buildout, I use the
`--version` option of the bootstrap.py script:: `--version` option of the bootstrap.py script::
$ python bootstrap.py --version 1.1.3 $ python bootstrap.py --version 1.1.3
The `zc.buildout project <http://svn.zope.org/zc.buildout/trunk>`_ The `zc.buildout project <http://svn.zope.org/zc.buildout/trunk>`_
is a slightly more complex example of this type of buildout. is a slightly more complex example of this type of buildout.
...@@ -196,5 +191,4 @@ Please send questions and comments to the ...@@ -196,5 +191,4 @@ Please send questions and comments to the
`distutils SIG mailing list <mailto://distutils-sig@python.org>`_. `distutils SIG mailing list <mailto://distutils-sig@python.org>`_.
Report bugs using the `zc.buildout Launchpad Bug Tracker Report bugs using the `zc.buildout Launchpad Bug Tracker
<https://launchpad.net/products/zc.buildout/+bugs>`_. <https://launchpad.net/zc.buildout/+bugs>`_.
...@@ -20,105 +20,109 @@ use the -c option to specify an alternate configuration file. ...@@ -20,105 +20,109 @@ use the -c option to specify an alternate configuration file.
$Id$ $Id$
""" """
import os, re, shutil, sys, tempfile, textwrap, urllib, urllib2 import os, shutil, sys, tempfile, textwrap, urllib, urllib2
from optparse import OptionParser
# We have to manually parse our options rather than using one of the stdlib
# tools because we want to pass the ones we don't recognize along to is_jython = sys.platform.startswith('java')
# zc.buildout.buildout.main.
setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
configuration = { distribute_source = 'http://python-distribute.org/distribute_setup.py'
'--ez_setup-source': 'http://peak.telecommunity.com/dist/ez_setup.py',
'--version': '', # parsing arguments
'--download-base': None, def normalize_to_url(option, opt_str, value, parser):
'--eggs': None} if value:
if '://' not in value: # It doesn't smell like a URL.
helpstring = __doc__ + textwrap.dedent(''' value = 'file://%s' % (
This script recognizes the following options itself. The first option it urllib.pathname2url(
encounters that is not one of these will cause the script to stop parsing os.path.abspath(os.path.expanduser(value))),)
options and pass the rest on to buildout. Therefore, if you want to use if opt_str == '--download-base' and not value.endswith('/'):
any of the following options *and* buildout command-line options like # Download base needs a trailing slash to make the world happy.
-c, first use the following options, and then use the buildout options. value += '/'
Options:
--version=ZC_BUILDOUT_VERSION
Specify a version number of the zc.buildout to use
--ez_setup-source=URL_OR_FILE
Specify a URL or file location for the ez_setup file.
Defaults to
%(--ez_setup-source)s
--download-base=URL_OR_DIRECTORY
Specify a URL or directory for downloading setuptools and
zc.buildout. Defaults to PyPI.
--eggs=DIRECTORY
Specify a directory for storing eggs. Defaults to a temporary
directory that is deleted when the bootstrap script completes.
By using --ez_setup-source and --download-base to point to local resources,
you can keep this script from going over the network.
''' % configuration)
match_equals = re.compile(r'(%s)=(.*)' % ('|'.join(configuration),)).match
args = sys.argv[1:]
if args == ['--help']:
print helpstring
sys.exit(0)
# If we end up using a temporary directory for storing our eggs, this will
# hold the path of that directory. On the other hand, if an explicit directory
# is specified in the argv, this will remain None.
tmpeggs = None
while args:
val = args[0]
if val in configuration:
del args[0]
if not args or args[0].startswith('-'):
print "ERROR: %s requires an argument."
print helpstring
sys.exit(1)
configuration[val] = args[0]
else: else:
match = match_equals(val) value = None
if match and match.group(1) in configuration: name = opt_str[2:].replace('-', '_')
configuration[match.group(1)] = match.group(2) setattr(parser.values, name, value)
else:
break usage = '''\
del args[0] [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
for name in ('--ez_setup-source', '--download-base'): Bootstraps a buildout-based project.
val = configuration[name]
if val is not None and '://' not in val: # We're being lazy. Simply run this script in a directory containing a buildout.cfg, using the
configuration[name] = 'file://%s' % ( Python that you want bin/buildout to use.
urllib.pathname2url(os.path.abspath(os.path.expanduser(val))),)
Note that by using --setup-source and --download-base to point to
if (configuration['--download-base'] and local resources, you can keep this script from going over the network.
not configuration['--download-base'].endswith('/')): '''
# Download base needs a trailing slash to make the world happy.
configuration['--download-base'] += '/' parser = OptionParser(usage=usage)
parser.add_option("-v", "--version", dest="version",
if not configuration['--eggs']: help="use a specific zc.buildout version")
configuration['--eggs'] = tmpeggs = tempfile.mkdtemp() parser.add_option("-d", "--distribute",
action="store_true", dest="use_distribute", default=False,
help="Use Distribute rather than Setuptools.")
parser.add_option("--setup-source", action="callback", dest="setup_source",
callback=normalize_to_url, nargs=1, type="string",
help=("Specify a URL or file location for the setup file. "
"If you use Setuptools, this will default to " +
setuptools_source + "; if you use Distribute, this "
"will default to " + distribute_source +"."))
parser.add_option("--download-base", action="callback", dest="download_base",
callback=normalize_to_url, nargs=1, type="string",
help=("Specify a URL or directory for downloading "
"zc.buildout and either Setuptools or Distribute. "
"Defaults to PyPI."))
parser.add_option("--eggs",
help=("Specify a directory for storing eggs. Defaults to "
"a temporary directory that is deleted when the "
"bootstrap script completes."))
parser.add_option("-c", None, action="store", dest="config_file",
help=("Specify the path to the buildout configuration "
"file to be used."))
options, args = parser.parse_args()
# if -c was provided, we push it back into args for buildout' main function
if options.config_file is not None:
args += ['-c', options.config_file]
if options.eggs:
eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
else: else:
configuration['--eggs'] = os.path.abspath( eggs_dir = tempfile.mkdtemp()
os.path.expanduser(configuration['--eggs']))
# The requirement is what we will pass to setuptools to specify zc.buildout. if options.setup_source is None:
requirement = 'zc.buildout' if options.use_distribute:
if configuration['--version']: options.setup_source = distribute_source
requirement += '==' + configuration['--version'] else:
options.setup_source = setuptools_source
args = args + ['bootstrap']
to_reload = False
try: try:
import setuptools # A flag. Sometimes pkg_resources is installed alone. import setuptools # A flag. Sometimes pkg_resources is installed alone.
import pkg_resources import pkg_resources
if not hasattr(pkg_resources, '_distribute'):
to_reload = True
raise ImportError
except ImportError: except ImportError:
ez_code = urllib2.urlopen( ez_code = urllib2.urlopen(
configuration['--ez_setup-source']).read().replace('\r\n', '\n') options.setup_source).read().replace('\r\n', '\n')
ez = {} ez = {}
exec ez_code in ez exec ez_code in ez
setuptools_args = dict(to_dir=configuration['--eggs'], download_delay=0) setup_args = dict(to_dir=eggs_dir, download_delay=0)
if configuration['--download-base']: if options.download_base:
setuptools_args['download_base'] = configuration['--download-base'] setup_args['download_base'] = options.download_base
ez['use_setuptools'](**setuptools_args) if options.use_distribute:
import pkg_resources setup_args['no_fake'] = True
ez['use_setuptools'](**setup_args)
if to_reload:
reload(pkg_resources)
else:
import pkg_resources
# This does not (always?) update the default working set. We will # This does not (always?) update the default working set. We will
# do it. # do it.
for path in sys.path: for path in sys.path:
...@@ -134,27 +138,35 @@ if sys.platform == 'win32': ...@@ -134,27 +138,35 @@ if sys.platform == 'win32':
else: else:
def quote (c): def quote (c):
return c return c
cmd = [quote(sys.executable), cmd = [quote(sys.executable),
'-c', '-c',
quote('from setuptools.command.easy_install import main; main()'), quote('from setuptools.command.easy_install import main; main()'),
'-mqNxd', '-mqNxd',
quote(configuration['--eggs'])] quote(eggs_dir)]
if configuration['--download-base']: if options.download_base:
cmd.extend(['-f', quote(configuration['--download-base'])]) cmd.extend(['-f', quote(options.download_base)])
requirement = 'zc.buildout'
if options.version:
requirement = '=='.join((requirement, options.version))
cmd.append(requirement) cmd.append(requirement)
if options.use_distribute:
setup_requirement = 'distribute'
else:
setup_requirement = 'setuptools'
ws = pkg_resources.working_set ws = pkg_resources.working_set
env = dict( env = dict(
os.environ, os.environ,
PYTHONPATH=ws.find(pkg_resources.Requirement.parse('setuptools')).location) PYTHONPATH=ws.find(
pkg_resources.Requirement.parse(setup_requirement)).location)
is_jython = sys.platform.startswith('java')
if is_jython: if is_jython:
import subprocess import subprocess
exitcode = subprocess.Popen(cmd, env=env).wait() exitcode = subprocess.Popen(cmd, env=env).wait()
else: # Windows needs this, apparently; otherwise we would prefer subprocess else: # Windows prefers this, apparently; otherwise we would prefer subprocess
exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
if exitcode != 0: if exitcode != 0:
sys.stdout.flush() sys.stdout.flush()
...@@ -164,10 +176,9 @@ if exitcode != 0: ...@@ -164,10 +176,9 @@ if exitcode != 0:
"were output by easy_install.") "were output by easy_install.")
sys.exit(exitcode) sys.exit(exitcode)
ws.add_entry(configuration['--eggs']) ws.add_entry(eggs_dir)
ws.require(requirement) ws.require(requirement)
import zc.buildout.buildout import zc.buildout.buildout
args.append('bootstrap')
zc.buildout.buildout.main(args) zc.buildout.buildout.main(args)
if tmpeggs is not None: if not options.eggs: # clean up temporary egg directory
shutil.rmtree(tmpeggs) shutil.rmtree(eggs_dir)
[buildout] [buildout]
develop = zc.recipe.egg_ z3c.recipe.scripts_ . develop = zc.recipe.egg_ .
parts = test oltest py parts = test oltest py
[py] [py]
...@@ -13,7 +13,6 @@ recipe = zc.recipe.testrunner ...@@ -13,7 +13,6 @@ recipe = zc.recipe.testrunner
eggs = eggs =
zc.buildout zc.buildout
zc.recipe.egg zc.recipe.egg
z3c.recipe.scripts
# Tests that can be run wo a network # Tests that can be run wo a network
[oltest] [oltest]
...@@ -21,9 +20,9 @@ recipe = zc.recipe.testrunner ...@@ -21,9 +20,9 @@ recipe = zc.recipe.testrunner
eggs = eggs =
zc.buildout zc.buildout
zc.recipe.egg zc.recipe.egg
z3c.recipe.scripts
defaults = defaults =
[ [
'-t', '-t',
'!(bootstrap|selectingpython|selecting-python)', '!(bootstrap|selectingpython|selecting-python)',
] ]
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
############################################################################## ##############################################################################
"""Bootstrap the buildout project itself. """Bootstrap the buildout project itself.
This is different from a normal boostrapping process because the This is different from a normal bootstrapping process because the
buildout egg itself is installed as a develop egg. buildout egg itself is installed as a develop egg.
$Id$ $Id$
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
# #
############################################################################## ##############################################################################
name = "zc.buildout" name = "zc.buildout"
version = "1.4.0dev" version = "1.4.4dev"
import os import os
from setuptools import setup from setuptools import setup
...@@ -48,6 +48,8 @@ long_description=( ...@@ -48,6 +48,8 @@ long_description=(
+ '\n' + + '\n' +
read('src', 'zc', 'buildout', 'easy_install.txt') read('src', 'zc', 'buildout', 'easy_install.txt')
+ '\n' + + '\n' +
read('src', 'zc', 'buildout', 'distribute.txt')
+ '\n' +
read('CHANGES.txt') read('CHANGES.txt')
+ '\n' + + '\n' +
'Download\n' 'Download\n'
...@@ -72,7 +74,7 @@ setup( ...@@ -72,7 +74,7 @@ setup(
long_description=long_description, long_description=long_description,
license = "ZPL 2.1", license = "ZPL 2.1",
keywords = "development build", keywords = "development build",
url='http://pypi.python.org/pypi/zc.buildout', url='http://buildout.org',
data_files = [('.', ['README.txt'])], data_files = [('.', ['README.txt'])],
packages = ['zc', 'zc.buildout'], packages = ['zc', 'zc.buildout'],
......
...@@ -119,9 +119,86 @@ Let's make sure the generated `buildout` script uses it:: ...@@ -119,9 +119,86 @@ Let's make sure the generated `buildout` script uses it::
zc.buildout.buildout.main() zc.buildout.buildout.main()
<BLANKLINE> <BLANKLINE>
You can specify a location of ez_setup.py, so you can rely on a local or remote `zc.buildout` now can also run with `Distribute` with the `--distribute`
location. We'll write our own ez_setup.py that we will also use to test some option::
other bootstrap options.
>>> print 'X'; print system(
... zc.buildout.easy_install._safe_arg(sys.executable)+' '+
... 'bootstrap.py --distribute'); print 'X' # doctest: +ELLIPSIS
...
X
...
Generated script '/sample/bin/buildout'.
<BLANKLINE>
X
Let's make sure the generated `buildout` script uses it::
>>> print open(buildout_script).read() # doctest: +ELLIPSIS
#...
<BLANKLINE>
import sys
sys.path[0:0] = [
'/sample/eggs/distribute-...egg',
'/sample/eggs/zc.buildout-...egg',
]
<BLANKLINE>
import zc.buildout.buildout
<BLANKLINE>
if __name__ == '__main__':
zc.buildout.buildout.main()
<BLANKLINE>
Make sure both options can be used together::
>>> print 'X'; print system(
... zc.buildout.easy_install._safe_arg(sys.executable)+' '+
... 'bootstrap.py --distribute --version 1.2.1'); print 'X'
... # doctest: +ELLIPSIS
...
X
...
Generated script '/sample/bin/buildout'.
<BLANKLINE>
X
Let's make sure the generated `buildout` script uses ``Distribute`` *and*
``zc.buildout-1.2.1``::
>>> print open(buildout_script).read() # doctest: +ELLIPSIS
#...
<BLANKLINE>
import sys
sys.path[0:0] = [
'/sample/eggs/distribute-...egg',
'/sample/eggs/zc.buildout-1.2.1...egg',
]
<BLANKLINE>
import zc.buildout.buildout
<BLANKLINE>
if __name__ == '__main__':
zc.buildout.buildout.main()
<BLANKLINE>
Last, the -c option needs to work on bootstrap.py::
>>> conf_file = os.path.join(sample_buildout, 'other.cfg')
>>> f = open(conf_file, 'w')
>>> f.write('[buildout]\nparts=\n\n')
>>> f.close()
>>> print 'X'; print system(
... zc.buildout.easy_install._safe_arg(sys.executable)+' '+
... 'bootstrap.py -c %s --distribute' % conf_file); print 'X' # doctest: +ELLIPSIS
...
X
...
Generated script '/sample/bin/buildout'.
<BLANKLINE>
X
You can specify a location of ez_setup.py or distribute_setup, so you
can rely on a local or remote location. We'll write our own ez_setup.py
that we will also use to test some other bootstrap options.
>>> write('ez_setup.py', '''\ >>> write('ez_setup.py', '''\
... def use_setuptools(**kwargs): ... def use_setuptools(**kwargs):
...@@ -131,7 +208,7 @@ other bootstrap options. ...@@ -131,7 +208,7 @@ other bootstrap options.
... ''') ... ''')
>>> print system( >>> print system(
... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+
... 'bootstrap.py --ez_setup-source=./ez_setup.py') ... 'bootstrap.py --setup-source=./ez_setup.py')
... # doctest: +ELLIPSIS ... # doctest: +ELLIPSIS
{'download_delay': 0, {'download_delay': 0,
'to_dir': '...'} 'to_dir': '...'}
...@@ -142,7 +219,7 @@ You can also pass a download-cache, and a place in which eggs should be stored ...@@ -142,7 +219,7 @@ You can also pass a download-cache, and a place in which eggs should be stored
>>> print system( >>> print system(
... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+
... 'bootstrap.py --ez_setup-source=./ez_setup.py '+ ... 'bootstrap.py --setup-source=./ez_setup.py '+
... '--download-base=./download-cache --eggs=eggs') ... '--download-base=./download-cache --eggs=eggs')
... # doctest: +ELLIPSIS ... # doctest: +ELLIPSIS
{'download_base': '/sample/download-cache/', {'download_base': '/sample/download-cache/',
...@@ -156,34 +233,33 @@ Here's the entire help text. ...@@ -156,34 +233,33 @@ Here's the entire help text.
... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+
... 'bootstrap.py --help'), ... 'bootstrap.py --help'),
... # doctest: +ELLIPSIS ... # doctest: +ELLIPSIS
Bootstrap a buildout-based project usage: [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
<BLANKLINE> <BLANKLINE>
Simply run this script in a directory containing a buildout.cfg. Bootstraps a buildout-based project.
The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
<BLANKLINE> <BLANKLINE>
... Simply run this script in a directory containing a buildout.cfg, using the
Python that you want bin/buildout to use.
<BLANKLINE>
Note that by using --setup-source and --download-base to point to
local resources, you can keep this script from going over the network.
<BLANKLINE> <BLANKLINE>
This script recognizes the following options itself. The first option it
encounters that is not one of these will cause the script to stop parsing
options and pass the rest on to buildout. Therefore, if you want to use
any of the following options *and* buildout command-line options like
-c, first use the following options, and then use the buildout options.
<BLANKLINE>
Options:
--version=ZC_BUILDOUT_VERSION
Specify a version number of the zc.buildout to use
--ez_setup-source=URL_OR_FILE
Specify a URL or file location for the ez_setup file.
Defaults to
http://peak.telecommunity.com/dist/ez_setup.py
--download-base=URL_OR_DIRECTORY
Specify a URL or directory for downloading setuptools and
zc.buildout. Defaults to PyPI.
--eggs=DIRECTORY
Specify a directory for storing eggs. Defaults to a temporary
directory that is deleted when the bootstrap script completes.
<BLANKLINE>
By using --ez_setup-source and --download-base to point to local resources,
you can keep this script from going over the network.
<BLANKLINE> <BLANKLINE>
options:
-h, --help show this help message and exit
-v VERSION, --version=VERSION
use a specific zc.buildout version
-d, --distribute Use Distribute rather than Setuptools.
--setup-source=SETUP_SOURCE
Specify a URL or file location for the setup file. If
you use Setuptools, this will default to
http://peak.telecommunity.com/dist/ez_setup.py; if you
use Distribute, this will default to http://python-
distribute.org/distribute_setup.py.
--download-base=DOWNLOAD_BASE
Specify a URL or directory for downloading zc.buildout
and either Setuptools or Distribute. Defaults to PyPI.
--eggs=EGGS Specify a directory for storing eggs. Defaults to a
temporary directory that is deleted when the bootstrap
script completes.
-c CONFIG_FILE Specify the path to the buildout configuration file to
be used.
...@@ -837,7 +837,8 @@ class Buildout(UserDict.DictMixin): ...@@ -837,7 +837,8 @@ class Buildout(UserDict.DictMixin):
upgraded = [] upgraded = []
for project in 'zc.buildout', 'setuptools': for project in 'zc.buildout', 'setuptools':
req = pkg_resources.Requirement.parse(project) req = pkg_resources.Requirement.parse(project)
if ws.find(req) != pkg_resources.working_set.find(req): project_location = pkg_resources.working_set.find(req).location
if ws.find(req).location != project_location:
upgraded.append(ws.find(req)) upgraded.append(ws.find(req))
if not upgraded: if not upgraded:
......
Distribute Support
==================
Distribute is a drop-in replacement for Setuptools.
zc.buildout is now compatible with Distribute 0.6. To use Distribute in your
buildout, you need use the ``--distribute`` option of the ``bootstrap.py``
script::
$ python bootstrap.py --distribute
This will download and install the latest Distribute 0.6 release in the
``eggs`` directory, and use this version for the scripts that are created
in ``bin``.
Notice that if you have a shared eggs directory, a buildout that uses
Distribute will not interfer with other buildouts that are based on Setuptools
and that are sharing the same eggs directory.
Form more information about the Distribute project, see:
http://python-distribute.org
This diff is collapsed.
This diff is collapsed.
...@@ -28,7 +28,6 @@ import socket ...@@ -28,7 +28,6 @@ import socket
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
import textwrap
import threading import threading
import time import time
import urllib2 import urllib2
...@@ -106,16 +105,6 @@ def system(command, input=''): ...@@ -106,16 +105,6 @@ def system(command, input=''):
e.close() e.close()
return result return result
def call_py(interpreter, cmd, flags=None):
if sys.platform == 'win32':
args = ['"%s"' % arg for arg in (interpreter, flags, cmd) if arg]
args.insert(-1, '"-c"')
return system('"%s"' % ' '.join(args))
else:
cmd = repr(cmd)
return system(
' '.join(arg for arg in (interpreter, flags, '-c', cmd) if arg))
def get(url): def get(url):
return urllib2.urlopen(url).read() return urllib2.urlopen(url).read()
...@@ -127,12 +116,7 @@ def _runsetup(setup, executable, *args): ...@@ -127,12 +116,7 @@ def _runsetup(setup, executable, *args):
args = [zc.buildout.easy_install._safe_arg(arg) args = [zc.buildout.easy_install._safe_arg(arg)
for arg in args] for arg in args]
args.insert(0, '-q') args.insert(0, '-q')
env = dict(os.environ) args.append(dict(os.environ, PYTHONPATH=setuptools_location))
if executable == sys.executable:
env['PYTHONPATH'] = setuptools_location
# else pass an executable that has setuptools! See testselectingpython.py.
args.append(env)
here = os.getcwd() here = os.getcwd()
try: try:
...@@ -151,11 +135,6 @@ def sdist(setup, dest): ...@@ -151,11 +135,6 @@ def sdist(setup, dest):
def bdist_egg(setup, executable, dest): def bdist_egg(setup, executable, dest):
_runsetup(setup, executable, 'bdist_egg', '-d', dest) _runsetup(setup, executable, 'bdist_egg', '-d', dest)
def sys_install(setup, dest):
_runsetup(setup, sys.executable, 'install', '--install-purelib', dest,
'--record', os.path.join(dest, '__added_files__'),
'--single-version-externally-managed')
def find_python(version): def find_python(version):
e = os.environ.get('PYTHON%s' % version) e = os.environ.get('PYTHON%s' % version)
if e is not None: if e is not None:
...@@ -223,24 +202,6 @@ def wait_until(label, func, *args, **kw): ...@@ -223,24 +202,6 @@ def wait_until(label, func, *args, **kw):
time.sleep(0.01) time.sleep(0.01)
raise ValueError('Timed out waiting for: '+label) raise ValueError('Timed out waiting for: '+label)
def make_buildout():
# Create a basic buildout.cfg to avoid a warning from buildout:
open('buildout.cfg', 'w').write(
"[buildout]\nparts =\n"
)
# Use the buildout bootstrap command to create a buildout
zc.buildout.buildout.Buildout(
'buildout.cfg',
[('buildout', 'log-level', 'WARNING'),
# trick bootstrap into putting the buildout develop egg
# in the eggs dir.
('buildout', 'develop-eggs-directory', 'eggs'),
]
).bootstrap([])
# Create the develop-eggs dir, which didn't get created the usual
# way due to the trick above:
os.mkdir('develop-eggs')
def buildoutSetUp(test): def buildoutSetUp(test):
test.globs['__tear_downs'] = __tear_downs = [] test.globs['__tear_downs'] = __tear_downs = []
...@@ -294,7 +255,27 @@ def buildoutSetUp(test): ...@@ -294,7 +255,27 @@ def buildoutSetUp(test):
sample = tmpdir('sample-buildout') sample = tmpdir('sample-buildout')
os.chdir(sample) os.chdir(sample)
make_buildout()
# Create a basic buildout.cfg to avoid a warning from buildout:
open('buildout.cfg', 'w').write(
"[buildout]\nparts =\n"
)
# Use the buildout bootstrap command to create a buildout
zc.buildout.buildout.Buildout(
'buildout.cfg',
[('buildout', 'log-level', 'WARNING'),
# trick bootstrap into putting the buildout develop egg
# in the eggs dir.
('buildout', 'develop-eggs-directory', 'eggs'),
]
).bootstrap([])
# Create the develop-eggs dir, which didn't get created the usual
# way due to the trick above:
os.mkdir('develop-eggs')
def start_server(path): def start_server(path):
port, thread = _start_server(path, name=path) port, thread = _start_server(path, name=path)
...@@ -302,40 +283,6 @@ def buildoutSetUp(test): ...@@ -302,40 +283,6 @@ def buildoutSetUp(test):
register_teardown(lambda: stop_server(url, thread)) register_teardown(lambda: stop_server(url, thread))
return url return url
def make_py(initialization=''):
"""Returns paths to new executable and to its site-packages.
"""
buildout = tmpdir('executable_buildout')
site_packages_dir = os.path.join(buildout, 'site-packages')
mkdir(site_packages_dir)
old_wd = os.getcwd()
os.chdir(buildout)
make_buildout()
initialization = '\n'.join(
' ' + line for line in initialization.split('\n'))
install_develop(
'zc.recipe.egg', os.path.join(buildout, 'develop-eggs'))
install_develop(
'z3c.recipe.scripts', os.path.join(buildout, 'develop-eggs'))
write('buildout.cfg', textwrap.dedent('''\
[buildout]
parts = py
[py]
recipe = z3c.recipe.scripts
interpreter = py
initialization =
%(initialization)s
extra-paths = %(site-packages)s
eggs = setuptools
''') % {
'initialization': initialization,
'site-packages': site_packages_dir})
system(os.path.join(buildout, 'bin', 'buildout'))
os.chdir(old_wd)
return (
os.path.join(buildout, 'bin', 'py'), site_packages_dir)
test.globs.update(dict( test.globs.update(dict(
sample_buildout = sample, sample_buildout = sample,
ls = ls, ls = ls,
...@@ -346,7 +293,6 @@ def buildoutSetUp(test): ...@@ -346,7 +293,6 @@ def buildoutSetUp(test):
tmpdir = tmpdir, tmpdir = tmpdir,
write = write, write = write,
system = system, system = system,
call_py = call_py,
get = get, get = get,
cd = (lambda *path: os.chdir(os.path.join(*path))), cd = (lambda *path: os.chdir(os.path.join(*path))),
join = os.path.join, join = os.path.join,
...@@ -355,7 +301,6 @@ def buildoutSetUp(test): ...@@ -355,7 +301,6 @@ def buildoutSetUp(test):
start_server = start_server, start_server = start_server,
buildout = os.path.join(sample, 'bin', 'buildout'), buildout = os.path.join(sample, 'bin', 'buildout'),
wait_until = wait_until, wait_until = wait_until,
make_py = make_py
)) ))
zc.buildout.easy_install.prefer_final(prefer_final) zc.buildout.easy_install.prefer_final(prefer_final)
...@@ -547,14 +492,10 @@ def _normalize_path(match): ...@@ -547,14 +492,10 @@ def _normalize_path(match):
path = path[1:] path = path[1:]
return '/' + path.replace(os.path.sep, '/') return '/' + path.replace(os.path.sep, '/')
if sys.platform == 'win32':
sep = r'[\\/]' # Windows uses both sometimes.
else:
sep = re.escape(os.path.sep)
normalize_path = ( normalize_path = (
re.compile( re.compile(
r'''[^'" \t\n\r]+%(sep)s_[Tt][Ee][Ss][Tt]_%(sep)s([^"' \t\n\r]+)''' r'''[^'" \t\n\r]+\%(sep)s_[Tt][Ee][Ss][Tt]_\%(sep)s([^"' \t\n\r]+)'''
% dict(sep=sep)), % dict(sep=os.path.sep)),
_normalize_path, _normalize_path,
) )
......
This diff is collapsed.
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# FOR A PARTICULAR PURPOSE. # FOR A PARTICULAR PURPOSE.
# #
############################################################################## ##############################################################################
import os, re, subprocess, sys, textwrap, unittest import os, re, sys, unittest
from zope.testing import doctest, renormalizing from zope.testing import doctest, renormalizing
import zc.buildout.tests import zc.buildout.tests
import zc.buildout.testing import zc.buildout.testing
...@@ -36,40 +36,12 @@ We can specify a specific Python executable. ...@@ -36,40 +36,12 @@ We can specify a specific Python executable.
>>> ls(dest) >>> ls(dest)
d demo-0.3-py%(other_version)s.egg d demo-0.3-py%(other_version)s.egg
d demoneeded-1.1-py%(other_version)s.egg d demoneeded-1.1-py%(other_version)s.egg
d setuptools-0.6-py%(other_version)s.egg
""" % dict(other_version=other_version) """ % dict(other_version=other_version)
) )
def multi_python(test): def multi_python(test):
other_executable = zc.buildout.testing.find_python(other_version) other_executable = zc.buildout.testing.find_python(other_version)
command = textwrap.dedent('''\
try:
import setuptools
except ImportError:
import sys
sys.exit(1)
''')
if subprocess.call([other_executable, '-c', command],
env=os.environ):
# the other executable does not have setuptools. Get setuptools.
# We will do this using the same tools we are testing, for better or
# worse. Alternatively, we could try using bootstrap.
executable_dir = test.globs['tmpdir']('executable_dir')
executable_parts = os.path.join(executable_dir, 'parts')
test.globs['mkdir'](executable_parts)
ws = zc.buildout.easy_install.install(
['setuptools'], executable_dir,
index='http://www.python.org/pypi/',
always_unzip=True, executable=other_executable)
zc.buildout.easy_install.generate_scripts(
executable_dir, ws, other_executable, executable_parts,
reqs=['setuptools'], interpreter='py')
original_executable = other_executable
other_executable = os.path.join(executable_dir, 'py')
assert not subprocess.call(
[other_executable, '-c', command], env=os.environ), (
'test set up failed')
sample_eggs = test.globs['tmpdir']('sample_eggs') sample_eggs = test.globs['tmpdir']('sample_eggs')
os.mkdir(os.path.join(sample_eggs, 'index')) os.mkdir(os.path.join(sample_eggs, 'index'))
test.globs['sample_eggs'] = sample_eggs test.globs['sample_eggs'] = sample_eggs
......
...@@ -81,14 +81,13 @@ new versions found in new releases: ...@@ -81,14 +81,13 @@ new versions found in new releases:
Our buildout script has been updated to use the new eggs: Our buildout script has been updated to use the new eggs:
>>> cat(sample_buildout, 'bin', 'buildout') >>> cat(sample_buildout, 'bin', 'buildout')
#!/usr/local/bin/python2.4 -S #!/usr/local/bin/python2.4
<BLANKLINE> <BLANKLINE>
import sys import sys
sys.path[0:0] = [ sys.path[0:0] = [
'/sample-buildout/eggs/zc.buildout-99.99-py2.4.egg', '/sample-buildout/eggs/zc.buildout-99.99-py2.4.egg',
'/sample-buildout/eggs/setuptools-99.99-py2.4.egg', '/sample-buildout/eggs/setuptools-99.99-py2.4.egg',
] ]
<BLANKLINE>
<BLANKLINE> <BLANKLINE>
import zc.buildout.buildout import zc.buildout.buildout
<BLANKLINE> <BLANKLINE>
......
Installing setuptools/distribute
--------------------------------
Some initial test setup:
>>> import sys
>>> import zc.buildout
>>> dest = tmpdir('sample-install')
Setuptools (0.6something) is packaged as an ``.egg``. So when installing it,
the egg is downloaded and used. Distribute is packaged as a tarball, which
makes an easy_install call necessary. In older versions of buildout, the
``_call_easy_install()`` method would call ``_get_dist()`` to get hold of the
setuptools path for calling easy_install. When an updated "distribute" was
found, this would try an install again, leading to an infinite recursion.
The solution is to just use the setuptools location found at import time, like
happens with the buildout and setuptools location that is inserted in scripts'
paths.
We test this corner case by patching the ``_get_dist()`` call:
>>> def mock_get_dist(requirement, ws, always_unzip):
... raise RuntimeError("We should not get called")
When installing setuptools itself, we expect the "Getting dist" message not to
be printed. We call ``_call_easy_install()`` directly and get an error
because of a non-existing tarball, but that's the OK for this corner case
test: we only want to test that ``_get_dist()`` isn't getting called:
>>> class MockDist(object):
... def __str__(self):
... return 'nonexisting.tgz'
... @property
... def project_name(self):
... # Testing corner case: there *is* actually
... # a newer setuptools package on pypi than we
... # are running with, so it really installs it
... # and compares project_name. We're past the
... # point that we're testing, so we just raise
... # the normally expected error.
... raise zc.buildout.UserError(
... "Couldn't install: nonexisting.tgz")
>>> dist = MockDist()
>>> installer = zc.buildout.easy_install.Installer(
... dest=dest,
... links=[link_server],
... index=link_server+'index/',
... executable=sys.executable,
... always_unzip=True)
>>> installer._get_dist = mock_get_dist
>>> installer._call_easy_install('setuptools', None, dest, dist)
Traceback (most recent call last):
...
UserError: Couldn't install: nonexisting.tgz
Change History
**************
1.0.0
=====
Initial public version.
********************************
Buildout Script Recipe
********************************
.. contents::
The script recipe installs eggs into a buildout eggs directory, exactly
like zc.recipe.egg, and then generates scripts in a buildout bin
directory with egg paths baked into them.
##############################################################################
#
# Copyright (c) 2007 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Setup for z3c.recipe.scripts package
$Id: setup.py 106736 2009-12-18 02:33:08Z gary $
"""
version = '1.0'
import os
from setuptools import setup, find_packages
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
name = "z3c.recipe.scripts"
setup(
name = name,
version = version,
author = "Gary Poster",
author_email = "gary.poster@canonical.com",
description = "Recipe for installing Python scripts",
long_description = (
read('README.txt')
+ '\n' +
read('CHANGES.txt')
+ '\n' +
'Detailed Documentation\n'
'**********************\n'
+ '\n' +
read('src', 'z3c', 'recipe', 'scripts', 'README.txt')
+ '\n' +
'Download\n'
'*********\n'
),
keywords = "development build",
classifiers = [
'Development Status :: 5 - Production/Stable',
'Framework :: Buildout',
'Intended Audience :: Developers',
'License :: OSI Approved :: Zope Public License',
'Topic :: Software Development :: Build Tools',
'Topic :: Software Development :: Libraries :: Python Modules',
],
url='http://cheeseshop.python.org/pypi/z3c.recipe.scripts',
license = "ZPL 2.1",
packages = find_packages('src'),
package_dir = {'':'src'},
namespace_packages = ['z3c', 'z3c.recipe'],
install_requires = [
'zc.buildout >=1.2.0',
'zc.recipe.egg',
'setuptools'],
tests_require = ['zope.testing'],
test_suite = name+'.tests.test_suite',
entry_points = {'zc.buildout': ['default = %s:Scripts' % name,
'script = %s:Scripts' % name,
'scripts = %s:Scripts' % name,
'interpreter = %s:Interpreter' % name,
]
},
include_package_data = True,
zip_safe=False,
)
__import__('pkg_resources').declare_namespace(__name__)
__import__('pkg_resources').declare_namespace(__name__)
This diff is collapsed.
from z3c.recipe.scripts.scripts import Scripts, Interpreter
##############################################################################
#
# Copyright (c) 2009-2010 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Install scripts from eggs.
"""
import os
import zc.buildout
import zc.buildout.easy_install
from zc.recipe.egg.egg import ScriptBase
class Base(ScriptBase):
def __init__(self, buildout, name, options):
if 'extends' in options:
options.update(buildout[options['extends']])
super(Base, self).__init__(buildout, name, options)
self.default_eggs = '' # Disables feature from zc.recipe.egg.
b_options = buildout['buildout']
options['parts-directory'] = os.path.join(
b_options['parts-directory'], self.name)
value = options.setdefault(
'add-site-packages',
b_options.get('add-site-packages', 'false'))
if value not in ('true', 'false'):
raise zc.buildout.UserError(
"Invalid value for add-site-packages option: %s" %
(value,))
self.add_site_packages = (value == 'true')
value = options.setdefault(
'exec-sitecustomize',
b_options.get('exec-sitecustomize', 'false'))
if value not in ('true', 'false'):
raise zc.buildout.UserError(
"Invalid value for exec-sitecustomize option: %s" %
(value,))
self.exec_sitecustomize = (value == 'true')
class Interpreter(Base):
def __init__(self, buildout, name, options):
super(Interpreter, self).__init__(buildout, name, options)
options.setdefault('name', name)
def install(self):
reqs, ws = self.working_set()
options = self.options
generated = []
if not os.path.exists(options['parts-directory']):
os.mkdir(options['parts-directory'])
generated.append(options['parts-directory'])
generated.extend(zc.buildout.easy_install.generate_scripts(
options['bin-directory'], ws, options['executable'],
options['parts-directory'],
interpreter=options['name'],
extra_paths=self.extra_paths,
initialization=options.get('initialization', ''),
add_site_packages=self.add_site_packages,
exec_sitecustomize=self.exec_sitecustomize,
relative_paths=self._relative_paths,
))
return generated
update = install
class Scripts(Base):
def _install(self, reqs, ws, scripts):
options = self.options
generated = []
if not os.path.exists(options['parts-directory']):
os.mkdir(options['parts-directory'])
generated.append(options['parts-directory'])
generated.extend(zc.buildout.easy_install.generate_scripts(
options['bin-directory'], ws, options['executable'],
options['parts-directory'], reqs=reqs, scripts=scripts,
interpreter=options.get('interpreter'),
extra_paths=self.extra_paths,
initialization=options.get('initialization', ''),
add_site_packages=self.add_site_packages,
exec_sitecustomize=self.exec_sitecustomize,
relative_paths=self._relative_paths,
script_arguments=options.get('arguments', ''),
script_initialization=options.get('script-initialization', '')
))
return generated
##############################################################################
#
# Copyright (c) 2006 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import os, re, shutil, sys
import zc.buildout.tests
import zc.buildout.testselectingpython
import zc.buildout.testing
import unittest
from zope.testing import doctest, renormalizing
# We do not explicitly test the recipe support for the ``eggs``,
# ``find-links``, and ``index`` options because they are used for most or
# all of the examples. The README tests ``extends``,
# ``include-site-customization`` and ``name``. That leaves ``python``,
# ``extra-paths``, ``initialization``, ``relative-paths``, and
# ``include-site-packages``.
def supports_python_option():
"""
This simply shows that the ``python`` option can specify another section to
find the ``executable``. (The ``python`` option defaults to looking in the
``buildout`` section.) We do this by creating a custom Python that will have
some initialization that we can look for.
>>> py_path, site_packages_path = make_py(initialization='''
... import os
... os.environ['zc.buildout'] = 'foo bar baz shazam'
... ''')
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [custom_python]
... executable = %(py_path)s
...
... [py]
... recipe = z3c.recipe.scripts:interpreter
... exec-sitecustomize = true
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)s/index
... python = custom_python
... ''' % dict(server=link_server, py_path=py_path))
>>> print system(buildout),
Installing py.
Getting distribution for 'demo<0.3'.
Got demo 0.2.
Getting distribution for 'demoneeded'.
Got demoneeded 1.2c1.
Generated interpreter '/sample-buildout/bin/py'.
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import os; print os.environ['zc.buildout']"'''),
foo bar baz shazam
"""
def interpreter_recipe_supports_extra_paths_option():
"""
This shows that specifying extra-paths will affect sys.path.
This recipe will not add paths that do not exist, so we create them.
>>> mkdir(sample_buildout, 'foo')
>>> mkdir(sample_buildout, 'foo', 'bar')
>>> mkdir(sample_buildout, 'spam')
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [py]
... recipe = z3c.recipe.scripts:interpreter
... find-links = %(server)s
... index = %(server)s/index
... extra-paths =
... ${buildout:directory}/foo/bar
... ${buildout:directory}/spam
... ''' % dict(server=link_server))
>>> print system(buildout),
Installing py.
Generated interpreter '/sample-buildout/bin/py'.
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import sys;print 'path' + ' '.join(sys.path)"''')
... # doctest:+ELLIPSIS
path.../foo/bar /sample-buildout/spam...
"""
def interpreter_recipe_supports_initialization_option():
"""
This simply shows that the ``initialization`` option can specify code to
run on initialization.
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [py]
... recipe = z3c.recipe.scripts:interpreter
... initialization =
... import os
... os.environ['zc.buildout'] = 'foo bar baz shazam'
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)s/index
... ''' % dict(server=link_server))
>>> print system(buildout),
Installing py.
Getting distribution for 'demo<0.3'.
Got demo 0.2.
Getting distribution for 'demoneeded'.
Got demoneeded 1.2c1.
Generated interpreter '/sample-buildout/bin/py'.
>>> cat(sample_buildout, 'parts', 'py', 'sitecustomize.py')
... # doctest: +NORMALIZE_WHITESPACE
<BLANKLINE>
import os
os.environ['zc.buildout'] = 'foo bar baz shazam'
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import os; print os.environ['zc.buildout']"'''),
foo bar baz shazam
This also works with the exec-sitecustomize option, processing local
initialization, and then the Python's initialization. We show this with a
custom Python.
>>> py_path, site_packages_path = make_py(initialization='''
... import os
... os.environ['zc.buildout'] = 'foo bar baz shazam'
... ''')
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [custom_python]
... executable = %(py_path)s
...
... [py]
... recipe = z3c.recipe.scripts:interpreter
... initialization =
... import os
... os.environ['zc.recipe.egg'] = 'baLOOba'
... exec-sitecustomize = true
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)s/index
... python = custom_python
... ''' % dict(server=link_server, py_path=py_path))
>>> print system(buildout),
Uninstalling py.
Installing py.
Generated interpreter '/sample-buildout/bin/py'.
>>> cat(sample_buildout, 'parts', 'py', 'sitecustomize.py')
... # doctest: +NORMALIZE_WHITESPACE
<BLANKLINE>
import os
os.environ['zc.recipe.egg'] = 'baLOOba'
<BLANKLINE>
# The following is from
# /executable_buildout/parts/py/sitecustomize.py
<BLANKLINE>
import os
os.environ['zc.buildout'] = 'foo bar baz shazam'
>>> print system(join(sample_buildout, 'bin', 'py') + ' -c ' +
... '''"import os; print os.environ['zc.recipe.egg']"'''),
baLOOba
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import os; print os.environ['zc.buildout']"'''),
foo bar baz shazam
"""
def interpreter_recipe_supports_relative_paths_option():
"""
This shows that the relative-paths option affects the code for inserting
paths into sys.path.
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [py]
... recipe = z3c.recipe.scripts:interpreter
... find-links = %(server)s
... index = %(server)s/index
... relative-paths = true
... extra-paths =
... /foo/bar
... ${buildout:directory}/spam
... ''' % dict(server=link_server))
>>> print system(buildout),
Installing py.
Generated interpreter '/sample-buildout/bin/py'.
Let's look at the site.py that was generated:
>>> import sys
>>> sys.stdout.write('#'); cat(sample_buildout, 'parts', 'py', 'site.py')
... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
#...
def addsitepackages(known_paths):
paths = []
<BLANKLINE>
import os
<BLANKLINE>
join = os.path.join
base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
base = os.path.dirname(base)
base = os.path.dirname(base)
paths[0:0] = [ # eggs
'/foo/bar',
join(base, 'spam')
]...
"""
def setUp(test):
zc.buildout.tests.easy_install_SetUp(test)
zc.buildout.testing.install_develop('zc.recipe.egg', test)
zc.buildout.testing.install_develop('z3c.recipe.scripts', test)
def setUpSelecting(test):
zc.buildout.testselectingpython.setup(test)
zc.buildout.testing.install_develop('zc.recipe.egg', test)
zc.buildout.testing.install_develop('z3c.recipe.scripts', test)
def test_suite():
suite = unittest.TestSuite((
doctest.DocFileSuite(
'README.txt',
setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([
zc.buildout.testing.normalize_path,
zc.buildout.testing.normalize_endings,
zc.buildout.testing.normalize_script,
zc.buildout.testing.normalize_egg_py,
zc.buildout.tests.normalize_bang,
(re.compile(r'zc.buildout(-\S+)?[.]egg(-link)?'),
'zc.buildout.egg'),
(re.compile('[-d] setuptools-[^-]+-'), 'setuptools-X-'),
(re.compile(r'setuptools-[\w.]+-py'), 'setuptools-X-py'),
(re.compile(r'eggs\\\\demo'), 'eggs/demo'),
(re.compile(r'[a-zA-Z]:\\\\foo\\\\bar'), '/foo/bar'),
(re.compile(r'\#!\S+\bpython\S*'), '#!/usr/bin/python'),
# Normalize generate_script's Windows interpreter to UNIX:
(re.compile(r'\nimport subprocess\n'), '\n'),
(re.compile('subprocess\\.call\\(argv, env=environ\\)'),
'os.execve(sys.executable, argv, environ)'),
])
),
doctest.DocTestSuite(
setUp=setUp,
tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([
zc.buildout.testing.normalize_path,
zc.buildout.testing.normalize_endings,
zc.buildout.testing.normalize_egg_py,
(re.compile(r'[a-zA-Z]:\\\\foo\\\\bar'), '/foo/bar'),
]),
),
))
return suite
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
...@@ -46,7 +46,7 @@ We have a link server that has a number of distributions: ...@@ -46,7 +46,7 @@ We have a link server that has a number of distributions:
<a href="other-1.0-py2.3.egg">other-1.0-py2.3.egg</a><br> <a href="other-1.0-py2.3.egg">other-1.0-py2.3.egg</a><br>
</body></html> </body></html>
We have a sample buildout. Let's update its configuration file to We have a sample buildout. Let's update it's configuration file to
install the demo package. install the demo package.
>>> write(sample_buildout, 'buildout.cfg', >>> write(sample_buildout, 'buildout.cfg',
...@@ -154,8 +154,6 @@ dependent-scripts ...@@ -154,8 +154,6 @@ dependent-scripts
interpreter interpreter
The name of a script to generate that allows access to a Python The name of a script to generate that allows access to a Python
interpreter that has the path set based on the eggs installed. interpreter that has the path set based on the eggs installed.
(See the ``z3c.recipe.scripts`` recipe for a more full-featured
interpreter.)
extra-paths extra-paths
Extra paths to include in a generated script. Extra paths to include in a generated script.
...@@ -189,7 +187,7 @@ Let's add an interpreter option: ...@@ -189,7 +187,7 @@ Let's add an interpreter option:
... interpreter = py-demo ... interpreter = py-demo
... """ % dict(server=link_server)) ... """ % dict(server=link_server))
Note that we omitted the entry point name from the recipe Note that we ommitted the entry point name from the recipe
specification. We were able to do this because the scripts recipe is specification. We were able to do this because the scripts recipe is
the default entry point for the zc.recipe.egg egg. the default entry point for the zc.recipe.egg egg.
...@@ -375,7 +373,7 @@ extra-paths option: ...@@ -375,7 +373,7 @@ extra-paths option:
Let's look at the script that was generated: Let's look at the script that was generated:
>>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE >>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE
#!/usr/local/bin/python2.4 -S #!/usr/local/bin/python2.4
<BLANKLINE> <BLANKLINE>
import sys import sys
sys.path[0:0] = [ sys.path[0:0] = [
...@@ -385,7 +383,6 @@ Let's look at the script that was generated: ...@@ -385,7 +383,6 @@ Let's look at the script that was generated:
'/sample-buildout/spam', '/sample-buildout/spam',
] ]
<BLANKLINE> <BLANKLINE>
<BLANKLINE>
import eggrecipedemo import eggrecipedemo
<BLANKLINE> <BLANKLINE>
if __name__ == '__main__': if __name__ == '__main__':
...@@ -423,7 +420,7 @@ breaking scripts. ...@@ -423,7 +420,7 @@ breaking scripts.
Let's look at the script that was generated: Let's look at the script that was generated:
>>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE >>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE
#!/usr/local/bin/python2.4 -S #!/usr/local/bin/python2.4
<BLANKLINE> <BLANKLINE>
import os import os
<BLANKLINE> <BLANKLINE>
...@@ -470,7 +467,7 @@ each individual script section: ...@@ -470,7 +467,7 @@ each individual script section:
Generated script '/sample-buildout/bin/foo'. Generated script '/sample-buildout/bin/foo'.
>>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE >>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE
#!/usr/local/bin/python2.4 -S #!/usr/local/bin/python2.4
<BLANKLINE> <BLANKLINE>
import os import os
<BLANKLINE> <BLANKLINE>
...@@ -523,7 +520,7 @@ to be included in generated scripts: ...@@ -523,7 +520,7 @@ to be included in generated scripts:
Generated script '/sample-buildout/bin/foo'. Generated script '/sample-buildout/bin/foo'.
>>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE >>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE
#!/usr/local/bin/python2.4 -S #!/usr/local/bin/python2.4
<BLANKLINE> <BLANKLINE>
import sys import sys
sys.path[0:0] = [ sys.path[0:0] = [
...@@ -581,16 +578,15 @@ declare entry points using the entry-points option: ...@@ -581,16 +578,15 @@ declare entry points using the entry-points option:
- other - other
>>> cat(sample_buildout, 'bin', 'other') >>> cat(sample_buildout, 'bin', 'other')
#!/usr/local/bin/python2.4 -S #!/usr/local/bin/python2.4
<BLANKLINE> <BLANKLINE>
import sys import sys
sys.path[0:0] = [ sys.path[0:0] = [
'/sample-buildout/eggs/demo-0.4c1-py2.4.egg', '/sample-buildout/eggs/demo-0.4c1-py2.4.egg',
'/sample-buildout/eggs/demoneeded-1.2c1-py2.4.egg', '/sample-buildout/eggs/demoneeded-1.2c1-py2.4.egg',
'/foo/bar', '/foo/bar',
'/sample-buildout/spam', '/sample-buildout/spam',
] ]
<BLANKLINE>
<BLANKLINE> <BLANKLINE>
import foo.bar import foo.bar
<BLANKLINE> <BLANKLINE>
...@@ -644,4 +640,3 @@ be made to contact an index server: ...@@ -644,4 +640,3 @@ be made to contact an index server:
Uninstalling bigdemo. Uninstalling bigdemo.
Installing demo. Installing demo.
Generated script '/sample-buildout/bin/foo'. Generated script '/sample-buildout/bin/foo'.
...@@ -15,7 +15,7 @@ To illustrate, we create a sample recipe that is a very thin layer ...@@ -15,7 +15,7 @@ To illustrate, we create a sample recipe that is a very thin layer
around the egg recipe: around the egg recipe:
>>> mkdir(sample_buildout, 'sample') >>> mkdir(sample_buildout, 'sample')
>>> write(sample_buildout, 'sample', 'sample.py', >>> write(sample_buildout, 'sample', 'sample.py',
... """ ... """
... import logging, os ... import logging, os
... import zc.recipe.egg ... import zc.recipe.egg
...@@ -53,7 +53,7 @@ of extra requirements to be included in the working set. ...@@ -53,7 +53,7 @@ of extra requirements to be included in the working set.
>>> write(sample_buildout, 'sample', 'setup.py', >>> write(sample_buildout, 'sample', 'setup.py',
... """ ... """
... from setuptools import setup ... from setuptools import setup
... ...
... setup( ... setup(
... name = "sample", ... name = "sample",
... entry_points = {'zc.buildout': ['default = sample:Sample']}, ... entry_points = {'zc.buildout': ['default = sample:Sample']},
...@@ -95,13 +95,12 @@ We can see that the options were augmented with additional data ...@@ -95,13 +95,12 @@ We can see that the options were augmented with additional data
computed by the egg recipe by looking at .installed.cfg: computed by the egg recipe by looking at .installed.cfg:
>>> cat(sample_buildout, '.installed.cfg') >>> cat(sample_buildout, '.installed.cfg')
... # doctest: +NORMALIZE_WHITESPACE
[buildout] [buildout]
installed_develop_eggs = /sample-buildout/develop-eggs/sample.egg-link installed_develop_eggs = /sample-buildout/develop-eggs/sample.egg-link
parts = sample-part parts = sample-part
<BLANKLINE> <BLANKLINE>
[sample-part] [sample-part]
__buildout_installed__ = __buildout_installed__ =
__buildout_signature__ = sample-6aWMvV2EJ9Ijq+bR8ugArQ== __buildout_signature__ = sample-6aWMvV2EJ9Ijq+bR8ugArQ==
zc.recipe.egg-cAsnudgkduAa/Fd+WJIM6Q== zc.recipe.egg-cAsnudgkduAa/Fd+WJIM6Q==
setuptools-0.6-py2.4.egg setuptools-0.6-py2.4.egg
...@@ -117,7 +116,6 @@ computed by the egg recipe by looking at .installed.cfg: ...@@ -117,7 +116,6 @@ computed by the egg recipe by looking at .installed.cfg:
extras = other extras = other
find-links = http://localhost:27071/ find-links = http://localhost:27071/
index = http://localhost:27071/index index = http://localhost:27071/index
python = buildout
recipe = sample recipe = sample
If we use the extra-paths option: If we use the extra-paths option:
......
...@@ -50,7 +50,7 @@ compiler ...@@ -50,7 +50,7 @@ compiler
swig swig
The path to the swig executable The path to the swig executable
swig-cpp swig-cpp
Make SWIG create C++ files (default is C) Make SWIG create C++ files (default is C)
swig-opts swig-opts
...@@ -73,14 +73,14 @@ index ...@@ -73,14 +73,14 @@ index
alternate index with this option. If you use the links option and alternate index with this option. If you use the links option and
if the links point to the needed distributions, then the index can if the links point to the needed distributions, then the index can
be anything and will be largely ignored. In the examples, here, be anything and will be largely ignored. In the examples, here,
we'll just point to an empty directory on our link server. This we'll just point to an empty directory on our link server. This
will make our examples run a little bit faster. will make our examples run a little bit faster.
python python
The name of a section to get the Python executable from. The name of a section to get the Python executable from.
If not specified, then the buildout python option is used. The If not specified, then the buildout python option is used. The
Python executable is found in the executable option of the named Python executable is found in the executable option of the named
section. section.
environment environment
The name of a section with additional environment variables. The The name of a section with additional environment variables. The
...@@ -150,7 +150,6 @@ eggs directory can be shared across multiple buildouts. ...@@ -150,7 +150,6 @@ eggs directory can be shared across multiple buildouts.
>>> ls(sample_buildout, 'develop-eggs') >>> ls(sample_buildout, 'develop-eggs')
d extdemo-1.4-py2.4-unix-i686.egg d extdemo-1.4-py2.4-unix-i686.egg
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link - zc.recipe.egg.egg-link
Note that no scripts or dependencies are installed. To install Note that no scripts or dependencies are installed. To install
...@@ -189,7 +188,7 @@ Let's define a script that uses out ext demo: ...@@ -189,7 +188,7 @@ Let's define a script that uses out ext demo:
... ...
... [demo] ... [demo]
... recipe = zc.recipe.egg ... recipe = zc.recipe.egg
... eggs = demo ... eggs = demo
... extdemo ... extdemo
... entry-points = demo=demo:main ... entry-points = demo=demo:main
... """ % dict(server=link_server)) ... """ % dict(server=link_server))
...@@ -232,7 +231,6 @@ We won't get an update. ...@@ -232,7 +231,6 @@ We won't get an update.
>>> ls(sample_buildout, 'develop-eggs') >>> ls(sample_buildout, 'develop-eggs')
- demo.egg-link - demo.egg-link
d extdemo-1.4-py2.4-unix-i686.egg d extdemo-1.4-py2.4-unix-i686.egg
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link - zc.recipe.egg.egg-link
But if we run the buildout in the default on-line and newest modes, we But if we run the buildout in the default on-line and newest modes, we
...@@ -250,7 +248,6 @@ version is imported: ...@@ -250,7 +248,6 @@ version is imported:
- demo.egg-link - demo.egg-link
d extdemo-1.4-py2.4-linux-i686.egg d extdemo-1.4-py2.4-linux-i686.egg
d extdemo-1.5-py2.4-linux-i686.egg d extdemo-1.5-py2.4-linux-i686.egg
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link - zc.recipe.egg.egg-link
Controlling the version used Controlling the version used
...@@ -273,7 +270,7 @@ We can specify a specific version using the egg option: ...@@ -273,7 +270,7 @@ We can specify a specific version using the egg option:
... ...
... [demo] ... [demo]
... recipe = zc.recipe.egg ... recipe = zc.recipe.egg
... eggs = demo ... eggs = demo
... extdemo ==1.4 ... extdemo ==1.4
... entry-points = demo=demo:main ... entry-points = demo=demo:main
... """ % dict(server=link_server)) ... """ % dict(server=link_server))
...@@ -290,7 +287,6 @@ We can specify a specific version using the egg option: ...@@ -290,7 +287,6 @@ We can specify a specific version using the egg option:
>>> ls(sample_buildout, 'develop-eggs') >>> ls(sample_buildout, 'develop-eggs')
- demo.egg-link - demo.egg-link
d extdemo-1.4-py2.4-linux-i686.egg d extdemo-1.4-py2.4-linux-i686.egg
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link - zc.recipe.egg.egg-link
...@@ -444,7 +440,7 @@ Create a clean buildout.cfg w/o the checkenv recipe, and delete the recipe: ...@@ -444,7 +440,7 @@ Create a clean buildout.cfg w/o the checkenv recipe, and delete the recipe:
Uninstalling extdemo. Uninstalling extdemo.
Installing extdemo. Installing extdemo.
zip_safe flag not set; analyzing archive contents... zip_safe flag not set; analyzing archive contents...
>>> rmdir(sample_buildout, 'recipes') >>> rmdir(sample_buildout, 'recipes')
...@@ -500,7 +496,7 @@ compiler ...@@ -500,7 +496,7 @@ compiler
swig swig
The path to the swig executable The path to the swig executable
swig-cpp swig-cpp
Make SWIG create C++ files (default is C) Make SWIG create C++ files (default is C)
swig-opts swig-opts
...@@ -510,7 +506,7 @@ python ...@@ -510,7 +506,7 @@ python
The name of a section to get the Python executable from. The name of a section to get the Python executable from.
If not specified, then the buildout python option is used. The If not specified, then the buildout python option is used. The
Python executable is found in the executable option of the named Python executable is found in the executable option of the named
section. section.
To illustrate this, we'll use a directory containing the extdemo To illustrate this, we'll use a directory containing the extdemo
example from the earlier section: example from the earlier section:
...@@ -536,7 +532,7 @@ example from the earlier section: ...@@ -536,7 +532,7 @@ example from the earlier section:
... ...
... [demo] ... [demo]
... recipe = zc.recipe.egg ... recipe = zc.recipe.egg
... eggs = demo ... eggs = demo
... extdemo ... extdemo
... entry-points = demo=demo:main ... entry-points = demo=demo:main
... """ % dict(extdemo=extdemo)) ... """ % dict(extdemo=extdemo))
...@@ -557,7 +553,6 @@ Our develop-eggs now includes an egg link for extdemo: ...@@ -557,7 +553,6 @@ Our develop-eggs now includes an egg link for extdemo:
>>> ls('develop-eggs') >>> ls('develop-eggs')
- demo.egg-link - demo.egg-link
- extdemo.egg-link - extdemo.egg-link
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link - zc.recipe.egg.egg-link
and the extdemo now has a built extension: and the extdemo now has a built extension:
......
...@@ -19,12 +19,11 @@ $Id$ ...@@ -19,12 +19,11 @@ $Id$
import logging, os, re, zipfile import logging, os, re, zipfile
import zc.buildout.easy_install import zc.buildout.easy_install
class Eggs(object): class Eggs(object):
def __init__(self, buildout, name, options): def __init__(self, buildout, name, options):
self.buildout = buildout self.buildout = buildout
self.name = self.default_eggs = name self.name = name
self.options = options self.options = options
b_options = buildout['buildout'] b_options = buildout['buildout']
links = options.get('find-links', b_options['find-links']) links = options.get('find-links', b_options['find-links'])
...@@ -53,7 +52,7 @@ class Eggs(object): ...@@ -53,7 +52,7 @@ class Eggs(object):
# verify that this is None, 'true' or 'false' # verify that this is None, 'true' or 'false'
get_bool(options, 'unzip') get_bool(options, 'unzip')
python = options.setdefault('python', b_options['python']) python = options.get('python', b_options['python'])
options['executable'] = buildout[python]['executable'] options['executable'] = buildout[python]['executable']
def working_set(self, extra=()): def working_set(self, extra=()):
...@@ -66,16 +65,15 @@ class Eggs(object): ...@@ -66,16 +65,15 @@ class Eggs(object):
distributions = [ distributions = [
r.strip() r.strip()
for r in options.get('eggs', self.default_eggs).split('\n') for r in options.get('eggs', self.name).split('\n')
if r.strip()] if r.strip()]
orig_distributions = distributions[:] orig_distributions = distributions[:]
distributions.extend(extra) distributions.extend(extra)
if b_options.get('offline') == 'true': if self.buildout['buildout'].get('offline') == 'true':
ws = zc.buildout.easy_install.working_set( ws = zc.buildout.easy_install.working_set(
distributions, options['executable'], distributions, options['executable'],
[options['develop-eggs-directory'], [options['develop-eggs-directory'], options['eggs-directory']]
options['eggs-directory']],
) )
else: else:
kw = {} kw = {}
...@@ -87,7 +85,7 @@ class Eggs(object): ...@@ -87,7 +85,7 @@ class Eggs(object):
index=self.index, index=self.index,
executable=options['executable'], executable=options['executable'],
path=[options['develop-eggs-directory']], path=[options['develop-eggs-directory']],
newest=b_options.get('newest') == 'true', newest=self.buildout['buildout'].get('newest') == 'true',
allow_hosts=self.allow_hosts, allow_hosts=self.allow_hosts,
**kw) **kw)
...@@ -99,19 +97,16 @@ class Eggs(object): ...@@ -99,19 +97,16 @@ class Eggs(object):
update = install update = install
class Scripts(Eggs):
class ScriptBase(Eggs):
def __init__(self, buildout, name, options): def __init__(self, buildout, name, options):
super(ScriptBase, self).__init__(buildout, name, options) super(Scripts, self).__init__(buildout, name, options)
b_options = buildout['buildout']
options['bin-directory'] = b_options['bin-directory'] options['bin-directory'] = buildout['buildout']['bin-directory']
options['_b'] = options['bin-directory'] # backward compat. options['_b'] = options['bin-directory'] # backward compat.
self.extra_paths = [ self.extra_paths = [
os.path.join(b_options['directory'], p.strip()) os.path.join(buildout['buildout']['directory'], p.strip())
for p in options.get('extra-paths', '').split('\n') for p in options.get('extra-paths', '').split('\n')
if p.strip() if p.strip()
] ]
...@@ -120,9 +115,11 @@ class ScriptBase(Eggs): ...@@ -120,9 +115,11 @@ class ScriptBase(Eggs):
relative_paths = options.get( relative_paths = options.get(
'relative-paths', b_options.get('relative-paths', 'false')) 'relative-paths',
buildout['buildout'].get('relative-paths', 'false')
)
if relative_paths == 'true': if relative_paths == 'true':
options['buildout-directory'] = b_options['directory'] options['buildout-directory'] = buildout['buildout']['directory']
self._relative_paths = options['buildout-directory'] self._relative_paths = options['buildout-directory']
else: else:
self._relative_paths = '' self._relative_paths = ''
...@@ -131,13 +128,12 @@ class ScriptBase(Eggs): ...@@ -131,13 +128,12 @@ class ScriptBase(Eggs):
parse_entry_point = re.compile( parse_entry_point = re.compile(
'([^=]+)=(\w+(?:[.]\w+)*):(\w+(?:[.]\w+)*)$' '([^=]+)=(\w+(?:[.]\w+)*):(\w+(?:[.]\w+)*)$'
).match ).match
def install(self): def install(self):
reqs, ws = self.working_set() reqs, ws = self.working_set()
options = self.options options = self.options
scripts = options.get('scripts') scripts = options.get('scripts')
if scripts or scripts is None or options.get('interpreter'): if scripts or scripts is None:
if scripts is not None: if scripts is not None:
scripts = scripts.split() scripts = scripts.split()
scripts = dict([ scripts = dict([
...@@ -161,31 +157,21 @@ class ScriptBase(Eggs): ...@@ -161,31 +157,21 @@ class ScriptBase(Eggs):
name = dist.project_name name = dist.project_name
if name != 'setuptools' and name not in reqs: if name != 'setuptools' and name not in reqs:
reqs.append(name) reqs.append(name)
return self._install(reqs, ws, scripts)
return ()
update = install
def _install(self, reqs, ws, scripts):
# Subclasses implement this.
raise NotImplementedError()
return zc.buildout.easy_install.scripts(
reqs, ws, options['executable'],
options['bin-directory'],
scripts=scripts,
extra_paths=self.extra_paths,
interpreter=options.get('interpreter'),
initialization=options.get('initialization', ''),
arguments=options.get('arguments', ''),
relative_paths=self._relative_paths,
)
class Scripts(ScriptBase): return ()
def _install(self, reqs, ws, scripts):
options = self.options
return zc.buildout.easy_install.scripts(
reqs, ws, options['executable'],
options['bin-directory'],
scripts=scripts,
extra_paths=self.extra_paths,
interpreter=options.get('interpreter'),
initialization=options.get('initialization', ''),
arguments=options.get('arguments', ''),
relative_paths=self._relative_paths
)
update = install
def get_bool(options, name, default=False): def get_bool(options, name, default=False):
value = options.get(name) value = options.get(name)
......
...@@ -25,7 +25,7 @@ We have a link server: ...@@ -25,7 +25,7 @@ We have a link server:
</body></html> </body></html>
We have a sample buildout. Let's update it's configuration file to We have a sample buildout. Let's update it's configuration file to
install the demo package using Python 2.4. install the demo package using Python 2.4.
>>> write(sample_buildout, 'buildout.cfg', >>> write(sample_buildout, 'buildout.cfg',
... """ ... """
...@@ -35,7 +35,7 @@ install the demo package using Python 2.4. ...@@ -35,7 +35,7 @@ install the demo package using Python 2.4.
... index = http://www.python.org/pypi/ ... index = http://www.python.org/pypi/
... ...
... [python2.4] ... [python2.4]
... executable = %(python24)s ... executable = %(python23)s
... ...
... [demo] ... [demo]
... recipe = zc.recipe.egg ... recipe = zc.recipe.egg
...@@ -43,7 +43,7 @@ install the demo package using Python 2.4. ...@@ -43,7 +43,7 @@ install the demo package using Python 2.4.
... find-links = %(server)s ... find-links = %(server)s
... python = python2.4 ... python = python2.4
... interpreter = py-demo ... interpreter = py-demo
... """ % dict(server=link_server, python24=other_executable)) ... """ % dict(server=link_server, python23=other_executable))
Now, if we run the buildout: Now, if we run the buildout:
...@@ -69,7 +69,7 @@ we'll get the Python 2.4 eggs for demo and demoneeded: ...@@ -69,7 +69,7 @@ we'll get the Python 2.4 eggs for demo and demoneeded:
d setuptools-0.6-py2.4.egg d setuptools-0.6-py2.4.egg
d setuptools-0.6-py2.5.egg d setuptools-0.6-py2.5.egg
- zc.buildout-1.0-py2.5.egg - zc.buildout-1.0-py2.5.egg
And the generated scripts invoke Python 2.4: And the generated scripts invoke Python 2.4:
>>> import sys >>> import sys
...@@ -81,8 +81,8 @@ And the generated scripts invoke Python 2.4: ...@@ -81,8 +81,8 @@ And the generated scripts invoke Python 2.4:
>>> shebang = f.readline().strip() >>> shebang = f.readline().strip()
>>> if shebang[:3] == '#!"' and shebang[-1] == '"': >>> if shebang[:3] == '#!"' and shebang[-1] == '"':
... shebang = '#!'+shebang[3:-1] ... shebang = '#!'+shebang[3:-1]
>>> assert shebang == '#!%s -S' % other_executable, ( >>> shebang == '#!' + other_executable
... repr((shebang, '#!' + other_executable))) True
>>> print f.read(), # doctest: +NORMALIZE_WHITESPACE >>> print f.read(), # doctest: +NORMALIZE_WHITESPACE
<BLANKLINE> <BLANKLINE>
import sys import sys
...@@ -104,8 +104,8 @@ And the generated scripts invoke Python 2.4: ...@@ -104,8 +104,8 @@ And the generated scripts invoke Python 2.4:
>>> shebang = f.readline().strip() >>> shebang = f.readline().strip()
>>> if shebang[:3] == '#!"' and shebang[-1] == '"': >>> if shebang[:3] == '#!"' and shebang[-1] == '"':
... shebang = '#!'+shebang[3:-1] ... shebang = '#!'+shebang[3:-1]
>>> assert shebang == '#!%s -S' % other_executable, ( >>> shebang == '#!' + other_executable
... repr((shebang, '#!' + other_executable))) True
>>> print f.read(), # doctest: +NORMALIZE_WHITESPACE >>> print f.read(), # doctest: +NORMALIZE_WHITESPACE
<BLANKLINE> <BLANKLINE>
import sys import sys
......
...@@ -36,7 +36,7 @@ def setUp(test): ...@@ -36,7 +36,7 @@ def setUp(test):
def setUpSelecting(test): def setUpSelecting(test):
zc.buildout.testselectingpython.setup(test) zc.buildout.testselectingpython.setup(test)
zc.buildout.testing.install_develop('zc.recipe.egg', test) zc.buildout.testing.install_develop('zc.recipe.egg', test)
def test_suite(): def test_suite():
suite = unittest.TestSuite(( suite = unittest.TestSuite((
doctest.DocFileSuite( doctest.DocFileSuite(
...@@ -67,7 +67,7 @@ def test_suite(): ...@@ -67,7 +67,7 @@ def test_suite():
'setuptools-\S+\s+' 'setuptools-\S+\s+'
'zc.buildout-\S+\s*' 'zc.buildout-\S+\s*'
), ),
'__buildout_signature__ = sample- zc.recipe.egg-\n'), '__buildout_signature__ = sample- zc.recipe.egg-'),
(re.compile('executable = [\S ]+python\S*', re.I), (re.compile('executable = [\S ]+python\S*', re.I),
'executable = python'), 'executable = python'),
(re.compile('find-links = http://localhost:\d+/'), (re.compile('find-links = http://localhost:\d+/'),
...@@ -89,7 +89,7 @@ def test_suite(): ...@@ -89,7 +89,7 @@ def test_suite():
(re.compile('extdemo[.]pyd'), 'extdemo.so') (re.compile('extdemo[.]pyd'), 'extdemo.so')
]), ]),
), ),
)) ))
if sys.version_info[:2] == (2, 5): if sys.version_info[:2] == (2, 5):
...@@ -115,7 +115,7 @@ def test_suite(): ...@@ -115,7 +115,7 @@ def test_suite():
]), ]),
), ),
) )
return suite return suite
if __name__ == '__main__': if __name__ == '__main__':
......
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