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

A -S branch

parents 337b7586 a542e58e
......@@ -6,34 +6,6 @@ Change History
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.
* New options let you specify where to find ez_setup.py and where to find
......@@ -47,24 +19,40 @@ New Features:
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.
This means, among other things, that ``bin/buildout -vv`` and
``bin/buildout annotate`` correctly list more of the options.
- Installing a namespace package using a Python that already has a package
in the same namespace (e.g., in the Python's site-packages) in some cases.
1.4.3 (2009-12-10)
==================
Bugs fixed:
- The error showed itself when at least two dependencies were in a shared
location like site-packages, and the first one met the "versions"
setting. The first dependency would be added, but subsequent
dependencies from the same location (e.g., site-packages) would use
the version of the package found in the shared location, ignoring the
version setting.
- Using pre-detected setuptools version for easy_installing tgz files. This
prevents a recursion error when easy_installing an upgraded "distribute"
tgz. Note that setuptools did not have this recursion problem solely
because it was packaged as an ``.egg``, which does not have to go through
the easy_install step.
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)
==================
......
......@@ -37,11 +37,6 @@ Existing recipes include:
dependencies. It installs their console-script entry points with
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>`_
The testrunner egg creates a test runner script for one or
more eggs.
......@@ -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::
$ python bootstrap.py --version 1.1.3
The `zc.buildout project <http://svn.zope.org/zc.buildout/trunk>`_
is a slightly more complex example of this type of buildout.
......@@ -196,5 +191,4 @@ Please send questions and comments to the
`distutils SIG mailing list <mailto://distutils-sig@python.org>`_.
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.
$Id$
"""
import os, re, shutil, sys, tempfile, textwrap, urllib, urllib2
# 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
# zc.buildout.buildout.main.
configuration = {
'--ez_setup-source': 'http://peak.telecommunity.com/dist/ez_setup.py',
'--version': '',
'--download-base': None,
'--eggs': None}
helpstring = __doc__ + textwrap.dedent('''
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.
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]
import os, shutil, sys, tempfile, textwrap, urllib, urllib2
from optparse import OptionParser
is_jython = sys.platform.startswith('java')
setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
distribute_source = 'http://python-distribute.org/distribute_setup.py'
# parsing arguments
def normalize_to_url(option, opt_str, value, parser):
if value:
if '://' not in value: # It doesn't smell like a URL.
value = 'file://%s' % (
urllib.pathname2url(
os.path.abspath(os.path.expanduser(value))),)
if opt_str == '--download-base' and not value.endswith('/'):
# Download base needs a trailing slash to make the world happy.
value += '/'
else:
match = match_equals(val)
if match and match.group(1) in configuration:
configuration[match.group(1)] = match.group(2)
else:
break
del args[0]
for name in ('--ez_setup-source', '--download-base'):
val = configuration[name]
if val is not None and '://' not in val: # We're being lazy.
configuration[name] = 'file://%s' % (
urllib.pathname2url(os.path.abspath(os.path.expanduser(val))),)
if (configuration['--download-base'] and
not configuration['--download-base'].endswith('/')):
# Download base needs a trailing slash to make the world happy.
configuration['--download-base'] += '/'
if not configuration['--eggs']:
configuration['--eggs'] = tmpeggs = tempfile.mkdtemp()
value = None
name = opt_str[2:].replace('-', '_')
setattr(parser.values, name, value)
usage = '''\
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
Bootstraps a buildout-based project.
Simply run this script in a directory containing a buildout.cfg, using the
Python that you want bin/buildout to use.
Note that by using --setup-source and --download-base to point to
local resources, you can keep this script from going over the network.
'''
parser = OptionParser(usage=usage)
parser.add_option("-v", "--version", dest="version",
help="use a specific zc.buildout version")
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:
configuration['--eggs'] = os.path.abspath(
os.path.expanduser(configuration['--eggs']))
eggs_dir = tempfile.mkdtemp()
# The requirement is what we will pass to setuptools to specify zc.buildout.
requirement = 'zc.buildout'
if configuration['--version']:
requirement += '==' + configuration['--version']
if options.setup_source is None:
if options.use_distribute:
options.setup_source = distribute_source
else:
options.setup_source = setuptools_source
args = args + ['bootstrap']
to_reload = False
try:
import setuptools # A flag. Sometimes pkg_resources is installed alone.
import pkg_resources
if not hasattr(pkg_resources, '_distribute'):
to_reload = True
raise ImportError
except ImportError:
ez_code = urllib2.urlopen(
configuration['--ez_setup-source']).read().replace('\r\n', '\n')
options.setup_source).read().replace('\r\n', '\n')
ez = {}
exec ez_code in ez
setuptools_args = dict(to_dir=configuration['--eggs'], download_delay=0)
if configuration['--download-base']:
setuptools_args['download_base'] = configuration['--download-base']
ez['use_setuptools'](**setuptools_args)
import pkg_resources
setup_args = dict(to_dir=eggs_dir, download_delay=0)
if options.download_base:
setup_args['download_base'] = options.download_base
if options.use_distribute:
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
# do it.
for path in sys.path:
......@@ -134,27 +138,35 @@ if sys.platform == 'win32':
else:
def quote (c):
return c
cmd = [quote(sys.executable),
'-c',
quote('from setuptools.command.easy_install import main; main()'),
'-mqNxd',
quote(configuration['--eggs'])]
quote(eggs_dir)]
if configuration['--download-base']:
cmd.extend(['-f', quote(configuration['--download-base'])])
if options.download_base:
cmd.extend(['-f', quote(options.download_base)])
requirement = 'zc.buildout'
if options.version:
requirement = '=='.join((requirement, options.version))
cmd.append(requirement)
if options.use_distribute:
setup_requirement = 'distribute'
else:
setup_requirement = 'setuptools'
ws = pkg_resources.working_set
env = dict(
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:
import subprocess
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]))
if exitcode != 0:
sys.stdout.flush()
......@@ -164,10 +176,9 @@ if exitcode != 0:
"were output by easy_install.")
sys.exit(exitcode)
ws.add_entry(configuration['--eggs'])
ws.add_entry(eggs_dir)
ws.require(requirement)
import zc.buildout.buildout
args.append('bootstrap')
zc.buildout.buildout.main(args)
if tmpeggs is not None:
shutil.rmtree(tmpeggs)
if not options.eggs: # clean up temporary egg directory
shutil.rmtree(eggs_dir)
[buildout]
develop = zc.recipe.egg_ z3c.recipe.scripts_ .
develop = zc.recipe.egg_ .
parts = test oltest py
[py]
......@@ -13,7 +13,6 @@ recipe = zc.recipe.testrunner
eggs =
zc.buildout
zc.recipe.egg
z3c.recipe.scripts
# Tests that can be run wo a network
[oltest]
......@@ -21,9 +20,9 @@ recipe = zc.recipe.testrunner
eggs =
zc.buildout
zc.recipe.egg
z3c.recipe.scripts
defaults =
[
'-t',
'!(bootstrap|selectingpython|selecting-python)',
]
......@@ -13,7 +13,7 @@
##############################################################################
"""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.
$Id$
......
......@@ -12,7 +12,7 @@
#
##############################################################################
name = "zc.buildout"
version = "1.4.0dev"
version = "1.4.4dev"
import os
from setuptools import setup
......@@ -48,6 +48,8 @@ long_description=(
+ '\n' +
read('src', 'zc', 'buildout', 'easy_install.txt')
+ '\n' +
read('src', 'zc', 'buildout', 'distribute.txt')
+ '\n' +
read('CHANGES.txt')
+ '\n' +
'Download\n'
......@@ -72,7 +74,7 @@ setup(
long_description=long_description,
license = "ZPL 2.1",
keywords = "development build",
url='http://pypi.python.org/pypi/zc.buildout',
url='http://buildout.org',
data_files = [('.', ['README.txt'])],
packages = ['zc', 'zc.buildout'],
......
......@@ -119,9 +119,86 @@ Let's make sure the generated `buildout` script uses it::
zc.buildout.buildout.main()
<BLANKLINE>
You can specify a location of ez_setup.py, 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.
`zc.buildout` now can also run with `Distribute` with the `--distribute`
option::
>>> 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', '''\
... def use_setuptools(**kwargs):
......@@ -131,7 +208,7 @@ other bootstrap options.
... ''')
>>> print system(
... 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
{'download_delay': 0,
'to_dir': '...'}
......@@ -142,7 +219,7 @@ You can also pass a download-cache, and a place in which eggs should be stored
>>> print system(
... 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')
... # doctest: +ELLIPSIS
{'download_base': '/sample/download-cache/',
......@@ -156,34 +233,33 @@ Here's the entire help text.
... zc.buildout.easy_install._safe_arg(sys.executable)+' '+
... 'bootstrap.py --help'),
... # doctest: +ELLIPSIS
Bootstrap a buildout-based project
usage: [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
<BLANKLINE>
Simply run this script in a directory containing a buildout.cfg.
The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
Bootstraps a buildout-based project.
<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>
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>
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):
upgraded = []
for project in 'zc.buildout', 'setuptools':
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))
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
import subprocess
import sys
import tempfile
import textwrap
import threading
import time
import urllib2
......@@ -106,16 +105,6 @@ def system(command, input=''):
e.close()
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):
return urllib2.urlopen(url).read()
......@@ -127,12 +116,7 @@ def _runsetup(setup, executable, *args):
args = [zc.buildout.easy_install._safe_arg(arg)
for arg in args]
args.insert(0, '-q')
env = dict(os.environ)
if executable == sys.executable:
env['PYTHONPATH'] = setuptools_location
# else pass an executable that has setuptools! See testselectingpython.py.
args.append(env)
args.append(dict(os.environ, PYTHONPATH=setuptools_location))
here = os.getcwd()
try:
......@@ -151,11 +135,6 @@ def sdist(setup, dest):
def bdist_egg(setup, executable, 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):
e = os.environ.get('PYTHON%s' % version)
if e is not None:
......@@ -223,24 +202,6 @@ def wait_until(label, func, *args, **kw):
time.sleep(0.01)
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):
test.globs['__tear_downs'] = __tear_downs = []
......@@ -294,7 +255,27 @@ def buildoutSetUp(test):
sample = tmpdir('sample-buildout')
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):
port, thread = _start_server(path, name=path)
......@@ -302,40 +283,6 @@ def buildoutSetUp(test):
register_teardown(lambda: stop_server(url, thread))
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(
sample_buildout = sample,
ls = ls,
......@@ -346,7 +293,6 @@ def buildoutSetUp(test):
tmpdir = tmpdir,
write = write,
system = system,
call_py = call_py,
get = get,
cd = (lambda *path: os.chdir(os.path.join(*path))),
join = os.path.join,
......@@ -355,7 +301,6 @@ def buildoutSetUp(test):
start_server = start_server,
buildout = os.path.join(sample, 'bin', 'buildout'),
wait_until = wait_until,
make_py = make_py
))
zc.buildout.easy_install.prefer_final(prefer_final)
......@@ -547,14 +492,10 @@ def _normalize_path(match):
path = path[1:]
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 = (
re.compile(
r'''[^'" \t\n\r]+%(sep)s_[Tt][Ee][Ss][Tt]_%(sep)s([^"' \t\n\r]+)'''
% dict(sep=sep)),
r'''[^'" \t\n\r]+\%(sep)s_[Tt][Ee][Ss][Tt]_\%(sep)s([^"' \t\n\r]+)'''
% dict(sep=os.path.sep)),
_normalize_path,
)
......
This diff is collapsed.
......@@ -11,7 +11,7 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import os, re, subprocess, sys, textwrap, unittest
import os, re, sys, unittest
from zope.testing import doctest, renormalizing
import zc.buildout.tests
import zc.buildout.testing
......@@ -36,40 +36,12 @@ We can specify a specific Python executable.
>>> ls(dest)
d demo-0.3-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)
)
def multi_python(test):
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')
os.mkdir(os.path.join(sample_eggs, 'index'))
test.globs['sample_eggs'] = sample_eggs
......
......@@ -81,14 +81,13 @@ new versions found in new releases:
Our buildout script has been updated to use the new eggs:
>>> cat(sample_buildout, 'bin', 'buildout')
#!/usr/local/bin/python2.4 -S
#!/usr/local/bin/python2.4
<BLANKLINE>
import sys
sys.path[0:0] = [
'/sample-buildout/eggs/zc.buildout-99.99-py2.4.egg',
'/sample-buildout/eggs/setuptools-99.99-py2.4.egg',
]
<BLANKLINE>
'/sample-buildout/eggs/zc.buildout-99.99-py2.4.egg',
'/sample-buildout/eggs/setuptools-99.99-py2.4.egg',
]
<BLANKLINE>
import zc.buildout.buildout
<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:
<a href="other-1.0-py2.3.egg">other-1.0-py2.3.egg</a><br>
</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.
>>> write(sample_buildout, 'buildout.cfg',
......@@ -154,8 +154,6 @@ dependent-scripts
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.
(See the ``z3c.recipe.scripts`` recipe for a more full-featured
interpreter.)
extra-paths
Extra paths to include in a generated script.
......@@ -189,7 +187,7 @@ Let's add an interpreter option:
... interpreter = py-demo
... """ % 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
the default entry point for the zc.recipe.egg egg.
......@@ -375,7 +373,7 @@ extra-paths option:
Let's look at the script that was generated:
>>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE
#!/usr/local/bin/python2.4 -S
#!/usr/local/bin/python2.4
<BLANKLINE>
import sys
sys.path[0:0] = [
......@@ -385,7 +383,6 @@ Let's look at the script that was generated:
'/sample-buildout/spam',
]
<BLANKLINE>
<BLANKLINE>
import eggrecipedemo
<BLANKLINE>
if __name__ == '__main__':
......@@ -423,7 +420,7 @@ breaking scripts.
Let's look at the script that was generated:
>>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE
#!/usr/local/bin/python2.4 -S
#!/usr/local/bin/python2.4
<BLANKLINE>
import os
<BLANKLINE>
......@@ -470,7 +467,7 @@ each individual script section:
Generated script '/sample-buildout/bin/foo'.
>>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE
#!/usr/local/bin/python2.4 -S
#!/usr/local/bin/python2.4
<BLANKLINE>
import os
<BLANKLINE>
......@@ -523,7 +520,7 @@ to be included in generated scripts:
Generated script '/sample-buildout/bin/foo'.
>>> cat(sample_buildout, 'bin', 'foo') # doctest: +NORMALIZE_WHITESPACE
#!/usr/local/bin/python2.4 -S
#!/usr/local/bin/python2.4
<BLANKLINE>
import sys
sys.path[0:0] = [
......@@ -581,16 +578,15 @@ declare entry points using the entry-points option:
- other
>>> cat(sample_buildout, 'bin', 'other')
#!/usr/local/bin/python2.4 -S
#!/usr/local/bin/python2.4
<BLANKLINE>
import sys
sys.path[0:0] = [
'/sample-buildout/eggs/demo-0.4c1-py2.4.egg',
'/sample-buildout/eggs/demoneeded-1.2c1-py2.4.egg',
'/foo/bar',
'/sample-buildout/spam',
]
<BLANKLINE>
'/sample-buildout/eggs/demo-0.4c1-py2.4.egg',
'/sample-buildout/eggs/demoneeded-1.2c1-py2.4.egg',
'/foo/bar',
'/sample-buildout/spam',
]
<BLANKLINE>
import foo.bar
<BLANKLINE>
......@@ -644,4 +640,3 @@ be made to contact an index server:
Uninstalling bigdemo.
Installing demo.
Generated script '/sample-buildout/bin/foo'.
......@@ -15,7 +15,7 @@ To illustrate, we create a sample recipe that is a very thin layer
around the egg recipe:
>>> mkdir(sample_buildout, 'sample')
>>> write(sample_buildout, 'sample', 'sample.py',
>>> write(sample_buildout, 'sample', 'sample.py',
... """
... import logging, os
... import zc.recipe.egg
......@@ -53,7 +53,7 @@ of extra requirements to be included in the working set.
>>> write(sample_buildout, 'sample', 'setup.py',
... """
... from setuptools import setup
...
...
... setup(
... name = "sample",
... entry_points = {'zc.buildout': ['default = sample:Sample']},
......@@ -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:
>>> cat(sample_buildout, '.installed.cfg')
... # doctest: +NORMALIZE_WHITESPACE
[buildout]
installed_develop_eggs = /sample-buildout/develop-eggs/sample.egg-link
parts = sample-part
<BLANKLINE>
[sample-part]
__buildout_installed__ =
__buildout_installed__ =
__buildout_signature__ = sample-6aWMvV2EJ9Ijq+bR8ugArQ==
zc.recipe.egg-cAsnudgkduAa/Fd+WJIM6Q==
setuptools-0.6-py2.4.egg
......@@ -117,7 +116,6 @@ computed by the egg recipe by looking at .installed.cfg:
extras = other
find-links = http://localhost:27071/
index = http://localhost:27071/index
python = buildout
recipe = sample
If we use the extra-paths option:
......
......@@ -50,7 +50,7 @@ compiler
swig
The path to the swig executable
swig-cpp
swig-cpp
Make SWIG create C++ files (default is C)
swig-opts
......@@ -73,14 +73,14 @@ index
alternate index with this option. If you use the links option and
if the links point to the needed distributions, then the index can
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.
python
The name of a section to get the Python executable from.
If not specified, then the buildout python option is used. The
Python executable is found in the executable option of the named
section.
section.
environment
The name of a section with additional environment variables. The
......@@ -150,7 +150,6 @@ eggs directory can be shared across multiple buildouts.
>>> ls(sample_buildout, 'develop-eggs')
d extdemo-1.4-py2.4-unix-i686.egg
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link
Note that no scripts or dependencies are installed. To install
......@@ -189,7 +188,7 @@ Let's define a script that uses out ext demo:
...
... [demo]
... recipe = zc.recipe.egg
... eggs = demo
... eggs = demo
... extdemo
... entry-points = demo=demo:main
... """ % dict(server=link_server))
......@@ -232,7 +231,6 @@ We won't get an update.
>>> ls(sample_buildout, 'develop-eggs')
- demo.egg-link
d extdemo-1.4-py2.4-unix-i686.egg
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link
But if we run the buildout in the default on-line and newest modes, we
......@@ -250,7 +248,6 @@ version is imported:
- demo.egg-link
d extdemo-1.4-py2.4-linux-i686.egg
d extdemo-1.5-py2.4-linux-i686.egg
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link
Controlling the version used
......@@ -273,7 +270,7 @@ We can specify a specific version using the egg option:
...
... [demo]
... recipe = zc.recipe.egg
... eggs = demo
... eggs = demo
... extdemo ==1.4
... entry-points = demo=demo:main
... """ % dict(server=link_server))
......@@ -290,7 +287,6 @@ We can specify a specific version using the egg option:
>>> ls(sample_buildout, 'develop-eggs')
- demo.egg-link
d extdemo-1.4-py2.4-linux-i686.egg
- z3c.recipe.scripts.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:
Uninstalling extdemo.
Installing extdemo.
zip_safe flag not set; analyzing archive contents...
>>> rmdir(sample_buildout, 'recipes')
......@@ -500,7 +496,7 @@ compiler
swig
The path to the swig executable
swig-cpp
swig-cpp
Make SWIG create C++ files (default is C)
swig-opts
......@@ -510,7 +506,7 @@ python
The name of a section to get the Python executable from.
If not specified, then the buildout python option is used. The
Python executable is found in the executable option of the named
section.
section.
To illustrate this, we'll use a directory containing the extdemo
example from the earlier section:
......@@ -536,7 +532,7 @@ example from the earlier section:
...
... [demo]
... recipe = zc.recipe.egg
... eggs = demo
... eggs = demo
... extdemo
... entry-points = demo=demo:main
... """ % dict(extdemo=extdemo))
......@@ -557,7 +553,6 @@ Our develop-eggs now includes an egg link for extdemo:
>>> ls('develop-eggs')
- demo.egg-link
- extdemo.egg-link
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link
and the extdemo now has a built extension:
......
......@@ -19,12 +19,11 @@ $Id$
import logging, os, re, zipfile
import zc.buildout.easy_install
class Eggs(object):
def __init__(self, buildout, name, options):
self.buildout = buildout
self.name = self.default_eggs = name
self.name = name
self.options = options
b_options = buildout['buildout']
links = options.get('find-links', b_options['find-links'])
......@@ -53,7 +52,7 @@ class Eggs(object):
# verify that this is None, 'true' or 'false'
get_bool(options, 'unzip')
python = options.setdefault('python', b_options['python'])
python = options.get('python', b_options['python'])
options['executable'] = buildout[python]['executable']
def working_set(self, extra=()):
......@@ -66,16 +65,15 @@ class Eggs(object):
distributions = [
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()]
orig_distributions = distributions[:]
distributions.extend(extra)
if b_options.get('offline') == 'true':
if self.buildout['buildout'].get('offline') == 'true':
ws = zc.buildout.easy_install.working_set(
distributions, options['executable'],
[options['develop-eggs-directory'],
options['eggs-directory']],
[options['develop-eggs-directory'], options['eggs-directory']]
)
else:
kw = {}
......@@ -87,7 +85,7 @@ class Eggs(object):
index=self.index,
executable=options['executable'],
path=[options['develop-eggs-directory']],
newest=b_options.get('newest') == 'true',
newest=self.buildout['buildout'].get('newest') == 'true',
allow_hosts=self.allow_hosts,
**kw)
......@@ -99,19 +97,16 @@ class Eggs(object):
update = install
class ScriptBase(Eggs):
class Scripts(Eggs):
def __init__(self, buildout, name, options):
super(ScriptBase, self).__init__(buildout, name, options)
b_options = buildout['buildout']
super(Scripts, self).__init__(buildout, name, options)
options['bin-directory'] = b_options['bin-directory']
options['bin-directory'] = buildout['buildout']['bin-directory']
options['_b'] = options['bin-directory'] # backward compat.
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')
if p.strip()
]
......@@ -120,9 +115,11 @@ class ScriptBase(Eggs):
relative_paths = options.get(
'relative-paths', b_options.get('relative-paths', 'false'))
'relative-paths',
buildout['buildout'].get('relative-paths', 'false')
)
if relative_paths == 'true':
options['buildout-directory'] = b_options['directory']
options['buildout-directory'] = buildout['buildout']['directory']
self._relative_paths = options['buildout-directory']
else:
self._relative_paths = ''
......@@ -131,13 +128,12 @@ class ScriptBase(Eggs):
parse_entry_point = re.compile(
'([^=]+)=(\w+(?:[.]\w+)*):(\w+(?:[.]\w+)*)$'
).match
def install(self):
reqs, ws = self.working_set()
options = self.options
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:
scripts = scripts.split()
scripts = dict([
......@@ -161,31 +157,21 @@ class ScriptBase(Eggs):
name = dist.project_name
if name != 'setuptools' and name not in reqs:
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):
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
)
return ()
update = install
def get_bool(options, name, default=False):
value = options.get(name)
......
......@@ -25,7 +25,7 @@ We have a link server:
</body></html>
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',
... """
......@@ -35,7 +35,7 @@ install the demo package using Python 2.4.
... index = http://www.python.org/pypi/
...
... [python2.4]
... executable = %(python24)s
... executable = %(python23)s
...
... [demo]
... recipe = zc.recipe.egg
......@@ -43,7 +43,7 @@ install the demo package using Python 2.4.
... find-links = %(server)s
... python = python2.4
... interpreter = py-demo
... """ % dict(server=link_server, python24=other_executable))
... """ % dict(server=link_server, python23=other_executable))
Now, if we run the buildout:
......@@ -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.5.egg
- zc.buildout-1.0-py2.5.egg
And the generated scripts invoke Python 2.4:
>>> import sys
......@@ -81,8 +81,8 @@ And the generated scripts invoke Python 2.4:
>>> shebang = f.readline().strip()
>>> if shebang[:3] == '#!"' and shebang[-1] == '"':
... shebang = '#!'+shebang[3:-1]
>>> assert shebang == '#!%s -S' % other_executable, (
... repr((shebang, '#!' + other_executable)))
>>> shebang == '#!' + other_executable
True
>>> print f.read(), # doctest: +NORMALIZE_WHITESPACE
<BLANKLINE>
import sys
......@@ -104,8 +104,8 @@ And the generated scripts invoke Python 2.4:
>>> shebang = f.readline().strip()
>>> if shebang[:3] == '#!"' and shebang[-1] == '"':
... shebang = '#!'+shebang[3:-1]
>>> assert shebang == '#!%s -S' % other_executable, (
... repr((shebang, '#!' + other_executable)))
>>> shebang == '#!' + other_executable
True
>>> print f.read(), # doctest: +NORMALIZE_WHITESPACE
<BLANKLINE>
import sys
......
......@@ -36,7 +36,7 @@ def setUp(test):
def setUpSelecting(test):
zc.buildout.testselectingpython.setup(test)
zc.buildout.testing.install_develop('zc.recipe.egg', test)
def test_suite():
suite = unittest.TestSuite((
doctest.DocFileSuite(
......@@ -67,7 +67,7 @@ def test_suite():
'setuptools-\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),
'executable = python'),
(re.compile('find-links = http://localhost:\d+/'),
......@@ -89,7 +89,7 @@ def test_suite():
(re.compile('extdemo[.]pyd'), 'extdemo.so')
]),
),
))
if sys.version_info[:2] == (2, 5):
......@@ -115,7 +115,7 @@ def test_suite():
]),
),
)
return suite
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