Commit ed79f5ee authored by Gary Poster's avatar Gary Poster
parents f551ee56 af2511a0
Change History Change History
************** **************
1.5.0 (unreleased)
==================
New features:
- zc.buildout supports Python 2.7.
- By default, Buildout and the bootstrap script now prefer final versions of
Buildout, recipes, and extensions. This can be changed by using the
--accept-buildout-test-releases flag (or -t for short) when calling
bootstrap. This will hopefully allow beta releases of these items to
be more easily and safely made in the future.
NOTE: dependencies of your own software are not affected by this new
behavior. Buildout continues to choose the newest available versions
of your dependencies regardless of whether they are final releases. To
prevent this, use the pre-existing switch ``prefer-final = true`` in
the [buildout] section of your configuration file (see
http://pypi.python.org/pypi/zc.buildout#preferring-final-releases) or
pin your versions using a versions section (see
http://pypi.python.org/pypi/zc.buildout#repeatable-buildouts-controlling-eggs-used).
Bugs fixed:
- You can now again use virtualenv with Buildout. The new features to let
buildout be used with a system Python are disabled in this configuration,
and the previous script generation behavior (1.4.3) is used, even if
the new function ``zc.buildout.easy_install.sitepackage_safe_scripts``
is used.
1.5.0b2 (2010-04-29)
====================
This was a re-release of 1.4.3 in order to keep 1.5.0b1 release from hurting
workflows that combined virtualenv with zc.buildout.
1.5.0b1 (2010-04-29) 1.5.0b1 (2010-04-29)
==================== ====================
...@@ -10,8 +46,13 @@ New Features: ...@@ -10,8 +46,13 @@ New Features:
both from command line and from config files. (gotcha) both from command line and from config files. (gotcha)
- Buildout can be safely used with a system Python (or any Python with code - Buildout can be safely used with a system Python (or any Python with code
in site-packages), as long as you use the new z3c.recipe.scripts in site-packages), as long as you use (1) A fresh checkout, (2) the
recipe to generate scripts and interpreters, rather than zc.recipe.egg. new bootstrap.py, and (3) recipes that use the new
``zc.buildout.easy_install.sitepackage_safe_scripts`` function to generate
scripts and interpreters. Many recipes will need to be updated to use
this new function. The scripts and interpreters generated by
``zc.recipe.egg`` will continue to use the older function, not safe
with system Pythons. Use the ``z3c.recipe.scripts`` as a replacement.
zc.recipe.egg is still a fully supported, and simpler, way of zc.recipe.egg is still a fully supported, and simpler, way of
generating scripts and interpreters if you are using a "clean" Python, generating scripts and interpreters if you are using a "clean" Python,
...@@ -42,15 +83,15 @@ New Features: ...@@ -42,15 +83,15 @@ New Features:
* The buildout script generated by bootstrap honors more of the settings * The buildout script generated by bootstrap honors more of the settings
in the designated configuration file (e.g., buildout.cfg). in the designated configuration file (e.g., buildout.cfg).
* Correcly handle systems where pkg_resources is present but the rest of * Correctly handle systems where pkg_resources is present but the rest of
setuptools is missing (like Ubuntu installs). setuptools is missing (like Ubuntu installs).
https://bugs.launchpad.net/zc.buildout/+bug/410528 https://bugs.launchpad.net/zc.buildout/+bug/410528
- You can develop zc.buildout using Distribute instead of Setuptools. Use - You can develop zc.buildout using Distribute instead of Setuptools. Use
the --distribute option on the dev.py script. (Releases should be tested the --distribute option on the dev.py script. (Releases should be tested
with both Distribute and Setuptools.) The tests for zc.buildout pass with both Distribute and Setuptools.) The tests for zc.buildout pass
with Setuptools and Python 2.4, 2.5, and 2.6; and with Distribute and with Setuptools and Python 2.4, 2.5, 2.6, and 2.7; and with Distribute and
Python 2.5 and 2.6. Using zc.buildout with Distribute and Python 2.4 Python 2.5, 2.6, and 2.7. Using zc.buildout with Distribute and Python 2.4
is not recommended. is not recommended.
- The ``distribute-version`` now works in the [buildout] section, mirroring - The ``distribute-version`` now works in the [buildout] section, mirroring
......
include *.txt
recursive-include src *.txt
exclude MANIFEST.in buildout.cfg .bzrignore
System Python and zc.buildout 1.5
*********************************
The 1.5 line of zc.buildout introduced a number of changes.
Problems
========
As usual, 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/zc.buildout/+bugs>`_.
If problems are keeping you from your work, here's an easy way to
revert to the old code temporarily: switch to a custom "emergency"
bootstrap script, available from
http://svn.zope.org/repos/main/zc.buildout/branches/1.4/bootstrap/bootstrap.py .
This customized script will select zc.buildout 1.4.4 by default.
zc.buildout 1.4.4 will not upgrade itself unless you explicitly specify
a new version. It will also prefer older versions of zc.recipe.egg and
some other common recipes. If you have trouble with other recipes,
consider using a standard buildout "versions" section to specify older
versions of these, as described in the Buildout documentation
(http://pypi.python.org/pypi/zc.buildout#repeatable-buildouts-controlling-eggs-used).
Working with a System Python
============================
While there are a number of new features available in zc.buildout 1.5,
the biggest is that Buildout itself supports usage with a system Python.
This can work if you follow a couple of simple rules.
1. Use the new bootstrap.py (available from
svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap/bootstrap.py).
2. Use buildout recipes that have been upgraded to work with zc.buildout 1.5
and higher. Specifically, they should use
``zc.buildout.easy_install.sitepackage_safe_scripts`` to generate
their scripts, if any, rather than ``zc.buildout.easy_install.scripts``.
See the `Recipes That Support a System Python`_ section below for more
details on recipes that are available as of this writing, and
`Updating Recipes to Support a System Python`_ for instructions on
how to update a recipe. Note that you should generally only need to
update recipes that generate scripts.
It's important to note that recipes not upgraded for zc.buildout 1.5.0
should continue to work--just not with a system Python.
Using a system Python is inherently fragile. Using a clean,
freshly-installed Python without customization in site-packages is more
robust and repeatable. See some of the regression tests added to the
1.5.0 line for the kinds of issues that you can encounter with a system
Python, and see
http://pypi.python.org/pypi/z3c.recipe.scripts#including-site-packages-and-sitecustomize
for more discussion.
However, using a system Python can be very convenient, and the
zc.buildout code for this feature has been tested by many users already.
Moreover, it has automated tests to exercise the problems that have been
encountered and fixed.
Recipes That Support a System Python
====================================
zc.recipe.egg continues to generate old-style scripts that are not safe
for use with a system Python. This was done for backwards
compatibility, because it is integral to so many buildouts and used as a
dependency of so many other recipes.
If you want to generate new-style scripts that do support system Python
usage, use z3c.recipe.scripts instead
(http://pypi.python.org/pypi/z3c.recipe.scripts). z3c.recipe.scripts has
the same script and interpreter generation options as zc.recipe.egg,
plus a few more for the new features mentioned above. In the simplest
case, you should be able to simply change ``recipe = zc.recipe.egg`` to
``recipe = z3c.recipe.scripts`` in the pertinent sections of your
buildout configuration and your generated scripts will work with a system
Python.
This is the only updated recipe as of this writing. Others should be
updated soon: see their change documents for details, or see `Updating
Recipes to Support a System Python`_ for instructions on how to update
recipes yourself.
Templates for creating Python scripts with the z3c.recipe.filetemplate
recipe can be easily changed to support a system Python.
- If you don't care about supporting relative paths, simply using a
generated interpreter with the eggs you want should be sufficient, as
it was before. For instance, if the interpreter is named "py", use
``#!${buildout:bin-directory/py}`` or ``#!/usr/bin/env
${buildout:bin-directory/py}``).
- If you do care about relative paths, (``relative-paths = true`` in
your buildout configuration), then z3c.recipe.scripts does require a
bit more changes, as is usual for the relative path support in that
package. First, use z3c.recipe.scripts to generate a script or
interpreter with the dependencies you want. This will create a
directory in ``parts`` that has a site.py and sitecustomize.py. Then,
begin your script as in the snippet below. The example assumes that
the z3c.recipe.scripts generated were from a Buildout configuration
section labeled "scripts": adjust accordingly.
::
#!${buildout:executable} -S
${python-relative-path-setup}
import sys
sys.path.insert(0, ${scripts:parts-directory|path-repr})
import site
Updating Recipes to Support a System Python
===========================================
You should generally only need to update recipes that generate scripts.
These recipes need to change from using ``zc.buildout.easy_install.scripts``
to be using ``zc.buildout.easy_install.sitepackage_safe_scripts``.
The signatures of the two functions are different. Please compare::
def scripts(
reqs, working_set, executable, dest,
scripts=None,
extra_paths=(),
arguments='',
interpreter=None,
initialization='',
relative_paths=False,
):
def sitepackage_safe_scripts(
dest, working_set, executable, site_py_dest,
reqs=(),
scripts=None,
interpreter=None,
extra_paths=(),
initialization='',
include_site_packages=False,
exec_sitecustomize=False,
relative_paths=False,
script_arguments='',
script_initialization='',
):
In most cases, the arguments are merely reordered. The ``reqs``
argument is no longer required in order to make it easier to generate an
interpreter alone. The ``arguments`` argument was renamed to
``script_arguments`` to clarify that it did not affect interpreter
generation.
The only new required argument is ``site_py_dest``. It must be the path
to a directory in which the customized site.py and sitecustomize.py
files will be written. A typical generation in a recipe will look like
this.
(In the recipe's __init__ method...)
::
self.options = options
b_options = buildout['buildout']
options['parts-directory'] = os.path.join(
b_options['parts-directory'], self.name)
(In the recipe's install method...)
::
options = self.options
generated = []
if not os.path.exists(options['parts-directory']):
os.mkdir(options['parts-directory'])
generated.append(options['parts-directory'])
Then ``options['parts-directory']`` can be used for the ``site_py_dest``
value.
If you want to support the other arguments (``include_site_packages``,
``exec_sitecustomize``, ``script_initialization``, as well as the
``allowed-eggs-from-site-packages`` option), you might want to look at
some of the code in
svn://svn.zope.org/repos/main/zc.buildout/trunk/z3c.recipe.scripts\_/src/z3c/recipe/scripts/scripts.py .
You might even be able to adopt some of it by subclassing or delegating.
The Scripts class in that file is the closest to what you might be used
to from zc.recipe.egg.
Important note for recipe authors: the code in recipes is *always run
without access to the site-packages*. This is irrespective of the
``include-site-packages`` option discussed elsewhere, which controls the
software being built, but not the environment in which Buildout itself runs.
virtualenv
==========
Using virtualenv (http://pypi.python.org/pypi/virtualenv) with the
--no-site-packages option already provided a simple way of using a
system Python. This is intended to continue to work, and some automated
tests exist to demonstrate this.
However, it is only supported to the degree that people have found it to
work in the past. The existing Buildout tests for virtualenv are only
for problems encountered previously. They are very far from
comprehensive.
Using Buildout with a system python has at least three advantages over
using Buildout in conjunction with virtualenv. They may or may not be
pertinent to your desired usage.
- Unlike ``virtualenv --no-site-packages``, Buildout's support allows you
to choose to let packages from your system Python be available to your
software (see ``include-site-packages`` in
http://pypi.python.org/pypi/z3c.recipe.scripts).
You can even specify which eggs installed in your system Python can be
allowed to fulfill some of your packages' dependencies (see
``allowed-eggs-from-site-packages`` in
http://pypi.python.org/pypi/z3c.recipe.scripts).
At the expense of some repeatability and platform dependency, this
flexibility means that, for instance, you can rely on
difficult-to-build eggs like lxml coming from your system Python.
- Buildout's implementation has a full set of automated tests.
- An integral Buildout implementation means fewer steps and fewer dependencies
to work with a system Python.
This diff is collapsed.
##############################################################################
#
# Copyright (c) 2006 Zope Foundation 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.
#
##############################################################################
"""Bootstrap a buildout-based project
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.
"""
import os, shutil, sys, tempfile, textwrap, urllib, urllib2
from optparse import OptionParser
if sys.platform == 'win32':
def quote(c):
if ' ' in c:
return '"%s"' % c # work around spawn lamosity on windows
else:
return c
else:
quote = str
# In order to be more robust in the face of system Pythons, we want to
# run without site-packages loaded. This is somewhat tricky, in
# particular because Python 2.6's distutils imports site, so starting
# with the -S flag is not sufficient. However, we'll start with that:
if 'site' in sys.modules:
# We will restart with python -S.
args = sys.argv[:]
args[0:0] = [sys.executable, '-S']
args = map(quote, args)
os.execv(sys.executable, args)
# Now we are running with -S. We'll get the clean sys.path, import site
# because distutils will do it later, and then reset the path and clean
# out any namespace packages from site-packages that might have been
# loaded by .pth files.
clean_path = sys.path[:]
import site
sys.path[:] = clean_path
for k, v in sys.modules.items():
if (hasattr(v, '__path__') and
len(v.__path__)==1 and
not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))):
# This is a namespace package. Remove it.
sys.modules.pop(k)
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:
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's 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:
eggs_dir = tempfile.mkdtemp()
if options.setup_source is None:
if options.use_distribute:
options.setup_source = distribute_source
else:
options.setup_source = setuptools_source
args = args + ['bootstrap']
try:
import pkg_resources
import setuptools # A flag. Sometimes pkg_resources is installed alone.
if not hasattr(pkg_resources, '_distribute'):
raise ImportError
except ImportError:
ez_code = urllib2.urlopen(
options.setup_source).read().replace('\r\n', '\n')
ez = {}
exec ez_code in ez
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)
reload(sys.modules['pkg_resources'])
import pkg_resources
# This does not (always?) update the default working set. We will
# do it.
for path in sys.path:
if path not in pkg_resources.working_set.entries:
pkg_resources.working_set.add_entry(path)
cmd = [quote(sys.executable),
'-c',
quote('from setuptools.command.easy_install import main; main()'),
'-mqNxd',
quote(eggs_dir)]
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(setup_requirement)).location)
if is_jython:
import subprocess
exitcode = subprocess.Popen(cmd, env=env).wait()
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()
sys.stderr.flush()
print ("An error occurred when trying to install zc.buildout. "
"Look above this message for any errors that "
"were output by easy_install.")
sys.exit(exitcode)
ws.add_entry(eggs_dir)
ws.require(requirement)
import zc.buildout.buildout
zc.buildout.buildout.main(args)
if not options.eggs: # clean up temporary egg directory
shutil.rmtree(eggs_dir)
...@@ -11,16 +11,15 @@ interpreter = py ...@@ -11,16 +11,15 @@ interpreter = py
[test] [test]
recipe = zc.recipe.testrunner recipe = zc.recipe.testrunner
eggs = eggs =
zc.buildout zc.buildout[test]
zc.recipe.egg zc.recipe.egg
z3c.recipe.scripts z3c.recipe.scripts
zope.testing
# Tests that can be run wo a network # Tests that can be run wo a network
[oltest] [oltest]
recipe = zc.recipe.testrunner recipe = zc.recipe.testrunner
eggs = eggs =
zc.buildout zc.buildout[test]
zc.recipe.egg zc.recipe.egg
z3c.recipe.scripts z3c.recipe.scripts
defaults = defaults =
......
...@@ -19,7 +19,7 @@ buildout egg itself is installed as a develop egg. ...@@ -19,7 +19,7 @@ buildout egg itself is installed as a develop egg.
$Id$ $Id$
""" """
import os, shutil, sys, subprocess, urllib2 import os, shutil, sys, subprocess, urllib2, subprocess
from optparse import OptionParser from optparse import OptionParser
if sys.platform == 'win32': if sys.platform == 'win32':
...@@ -31,11 +31,15 @@ if sys.platform == 'win32': ...@@ -31,11 +31,15 @@ if sys.platform == 'win32':
else: else:
quote = str quote = str
# Detect https://bugs.launchpad.net/virtualenv/+bug/572545 .
has_broken_dash_S = subprocess.call(
[sys.executable, '-Sc', 'import ConfigParser'])
# In order to be more robust in the face of system Pythons, we want to # In order to be more robust in the face of system Pythons, we want to
# run without site-packages loaded. This is somewhat tricky, in # run without site-packages loaded. This is somewhat tricky, in
# particular because Python 2.6's distutils imports site, so starting # particular because Python 2.6's distutils imports site, so starting
# with the -S flag is not sufficient. However, we'll start with that: # with the -S flag is not sufficient. However, we'll start with that:
if 'site' in sys.modules: if not has_broken_dash_S and 'site' in sys.modules:
# We will restart with python -S. # We will restart with python -S.
args = sys.argv[:] args = sys.argv[:]
args[0:0] = [sys.executable, '-S'] args[0:0] = [sys.executable, '-S']
...@@ -117,10 +121,14 @@ except ImportError: ...@@ -117,10 +121,14 @@ except ImportError:
env = os.environ.copy() # Windows needs yet-to-be-determined values from this. env = os.environ.copy() # Windows needs yet-to-be-determined values from this.
env['PYTHONPATH'] = os.path.dirname(pkg_resources.__file__) env['PYTHONPATH'] = os.path.dirname(pkg_resources.__file__)
subprocess.Popen(
[sys.executable] + cmd = [sys.executable,
['setup.py', '-q', 'develop', '-m', '-x', '-d', 'develop-eggs'], 'setup.py', '-q', 'develop', '-m', '-x', '-d', 'develop-eggs']
env=env).wait()
if not has_broken_dash_S:
cmd.insert(1, '-S')
subprocess.Popen(cmd, env=env).wait()
pkg_resources.working_set.add_entry('src') pkg_resources.working_set.add_entry('src')
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
# #
############################################################################## ##############################################################################
name = "zc.buildout" name = "zc.buildout"
version = "1.5.0dev" version = "1.5.0"
import os import os
from setuptools import setup from setuptools import setup
...@@ -23,6 +23,8 @@ def read(*rnames): ...@@ -23,6 +23,8 @@ def read(*rnames):
long_description=( long_description=(
read('README.txt') read('README.txt')
+ '\n' + + '\n' +
read('SYSTEM_PYTHON_HELP.txt')
+ '\n' +
'Detailed Documentation\n' 'Detailed Documentation\n'
'**********************\n' '**********************\n'
+ '\n' + + '\n' +
...@@ -83,6 +85,7 @@ setup( ...@@ -83,6 +85,7 @@ setup(
install_requires = 'setuptools', install_requires = 'setuptools',
include_package_data = True, include_package_data = True,
entry_points = entry_points, entry_points = entry_points,
extras_require = dict(test=['zope.testing']),
zip_safe=False, zip_safe=False,
classifiers = [ classifiers = [
'Intended Audience :: Developers', 'Intended Audience :: Developers',
......
...@@ -2,14 +2,14 @@ Allow hosts ...@@ -2,14 +2,14 @@ Allow hosts
----------- -----------
On some environments the links visited by `zc.buildout` can be forbidden On some environments the links visited by `zc.buildout` can be forbidden
by paranoiac firewalls. These URL might be on the chain of links by paranoiac firewalls. These URL might be on the chain of links
visited by `zc.buildout` whether they are defined in the `find-links` option visited by `zc.buildout` whether they are defined in the `find-links` option
or by various eggs in their `url`, `download_url` and `dependency_links` metadata. or by various eggs in their `url`, `download_url` and `dependency_links` metadata.
It is even harder to track that package_index works like a spider and It is even harder to track that package_index works like a spider and
might visit links and go to other location. might visit links and go to other location.
The `allow-hosts` option provides a way to prevent this, and The `allow-hosts` option provides a way to prevent this, and
works exactly like the one provided in `easy_install` works exactly like the one provided in `easy_install`
(see `easy_install allow-hosts option`_). (see `easy_install allow-hosts option`_).
...@@ -17,7 +17,7 @@ You can provide a list of allowed host, together with wildcards:: ...@@ -17,7 +17,7 @@ You can provide a list of allowed host, together with wildcards::
[buildout] [buildout]
... ...
allow-hosts = allow-hosts =
*.python.org *.python.org
example.com example.com
...@@ -36,7 +36,7 @@ Let's create a develop egg in our buildout that specifies ...@@ -36,7 +36,7 @@ Let's create a develop egg in our buildout that specifies
... zip_safe=True, version='1') ... zip_safe=True, version='1')
... ''') ... ''')
Now let's configure the buildout to use the develop egg, Now let's configure the buildout to use the develop egg,
together with some rules that disallow any website but PyPI and together with some rules that disallow any website but PyPI and
local files:: local files::
...@@ -55,14 +55,11 @@ local files:: ...@@ -55,14 +55,11 @@ local files::
Now we can run the buildout and make sure all attempts to dist.plone.org fails:: Now we can run the buildout and make sure all attempts to dist.plone.org fails::
>>> print system(buildout) >>> print system(buildout) # doctest: +ELLIPSIS
Develop: '/sample-buildout/allowdemo' Develop: '/sample-buildout/allowdemo'
Installing eggs. ...
<BLANKLINE>
Link to http://dist.plone.org ***BLOCKED*** by --allow-hosts Link to http://dist.plone.org ***BLOCKED*** by --allow-hosts
<BLANKLINE> ...
Couldn't find index page for 'kss.core' (maybe misspelled?)
Getting distribution for 'kss.core'.
While: While:
Installing eggs. Installing eggs.
Getting distribution for 'kss.core'. Getting distribution for 'kss.core'.
...@@ -91,14 +88,11 @@ XXX (showcase with a svn:// file) ...@@ -91,14 +88,11 @@ XXX (showcase with a svn:// file)
Now we can run the buildout and make sure all attempts to dist.plone.org fails:: Now we can run the buildout and make sure all attempts to dist.plone.org fails::
>>> print system(buildout) >>> print system(buildout) # doctest: +ELLIPSIS
Develop: '/sample-buildout/allowdemo' Develop: '/sample-buildout/allowdemo'
Installing eggs. ...
<BLANKLINE>
Link to http://dist.plone.org ***BLOCKED*** by --allow-hosts Link to http://dist.plone.org ***BLOCKED*** by --allow-hosts
<BLANKLINE> ...
Couldn't find index page for 'kss.core' (maybe misspelled?)
Getting distribution for 'kss.core'.
While: While:
Installing eggs. Installing eggs.
Getting distribution for 'kss.core'. Getting distribution for 'kss.core'.
...@@ -115,7 +109,7 @@ Test for 1.0.5 breakage as in https://bugs.launchpad.net/zc.buildout/+bug/239212 ...@@ -115,7 +109,7 @@ Test for 1.0.5 breakage as in https://bugs.launchpad.net/zc.buildout/+bug/239212
... [buildout] ... [buildout]
... parts=python ... parts=python
... foo = ${python:interpreter} ... foo = ${python:interpreter}
... ...
... [python] ... [python]
... recipe=zc.recipe.egg ... recipe=zc.recipe.egg
... eggs=zc.buildout ... eggs=zc.buildout
......
This diff is collapsed.
This diff is collapsed.
...@@ -729,6 +729,8 @@ COMMAND_LINE_VALUE). ...@@ -729,6 +729,8 @@ COMMAND_LINE_VALUE).
================== ==================
<BLANKLINE> <BLANKLINE>
[buildout] [buildout]
accept-buildout-test-releases= false
DEFAULT_VALUE
allow-hosts= * allow-hosts= *
DEFAULT_VALUE DEFAULT_VALUE
allow-picked-versions= true allow-picked-versions= true
...@@ -2227,6 +2229,7 @@ database is shown. ...@@ -2227,6 +2229,7 @@ database is shown.
<BLANKLINE> <BLANKLINE>
Configuration data: Configuration data:
[buildout] [buildout]
accept-buildout-test-releases = false
allow-hosts = * allow-hosts = *
allow-picked-versions = true allow-picked-versions = true
bin-directory = /sample-buildout/bin bin-directory = /sample-buildout/bin
...@@ -2484,25 +2487,33 @@ the buildout -o option. ...@@ -2484,25 +2487,33 @@ the buildout -o option.
Preferring Final Releases Preferring Final Releases
------------------------- -------------------------
Currently, when searching for new releases, the newest available Currently, when searching for new releases of your project's
release is used. This isn't usually ideal, as you may get a dependencies, the newest available release is used. This isn't usually
development release or alpha releases not ready to be widely used. ideal, as you may get a development release or alpha releases not ready
You can request that final releases be preferred using the prefer to be widely used. You can request that final releases be preferred
final option in the buildout section:: using the ``prefer-final`` option in the buildout section::
[buildout] [buildout]
... ...
prefer-final = true prefer-final = true
When the prefer-final option is set to true, then when searching for When the ``prefer-final`` option is set to true, then when searching for
new releases, final releases are preferred. If there are final new releases, final releases are preferred. If there are final
releases that satisfy distribution requirements, then those releases releases that satisfy distribution requirements, then those releases
are used even if newer non-final releases are available. The buildout are used even if newer non-final releases are available.
prefer-final option can be used to override this behavior.
In buildout version 2, all final releases will be preferred by
In buildout version 2, final releases will be preferred by default. default--that is ``prefer-final`` will also default to 'true'. You will
You will then need to use a false value for prefer-final to get the then need to use a 'false' value for ``prefer-final`` to get the newest
newest releases. releases.
A separate option controls the behavior of the build system itself.
When buildout looks for recipes, extensions, and for updates to itself,
it does prefer final releases by default, as of the 1.5.0 release. The
``accept-buildout-test-releases`` option will let you override this behavior.
However, it is typically changed by the --accept-buildout-test-releases
option to the bootstrap script, since bootstrapping is the first step to
selecting a buildout.
Finding distributions Finding distributions
--------------------- ---------------------
......
...@@ -5,12 +5,12 @@ Buildouts can be pretty complex. When things go wrong, it isn't ...@@ -5,12 +5,12 @@ Buildouts can be pretty complex. When things go wrong, it isn't
always obvious why. Errors can occur due to problems in user input or always obvious why. Errors can occur due to problems in user input or
due to bugs in zc.buildout or recipes. When an error occurs, Python's due to bugs in zc.buildout or recipes. When an error occurs, Python's
post-mortem debugger can be used to inspect the state of the buildout post-mortem debugger can be used to inspect the state of the buildout
or recipe code were there error occurred. To enable this, use the -D or recipe code where the error occurred. To enable this, use the -D
option to the buildout. Let's create a recipe that has a bug: option to the buildout. Let's create a recipe that has a bug:
>>> mkdir(sample_buildout, 'recipes') >>> mkdir(sample_buildout, 'recipes')
>>> write(sample_buildout, 'recipes', 'mkdir.py', >>> write(sample_buildout, 'recipes', 'mkdir.py',
... """ ... """
... import os, zc.buildout ... import os, zc.buildout
... ...
...@@ -35,7 +35,7 @@ option to the buildout. Let's create a recipe that has a bug: ...@@ -35,7 +35,7 @@ option to the buildout. Let's create a recipe that has a bug:
>>> write(sample_buildout, 'recipes', 'setup.py', >>> write(sample_buildout, 'recipes', 'setup.py',
... """ ... """
... from setuptools import setup ... from setuptools import setup
... ...
... setup(name = "recipes", ... setup(name = "recipes",
... entry_points = {'zc.buildout': ['mkdir = mkdir:Mkdir']}, ... entry_points = {'zc.buildout': ['mkdir = mkdir:Mkdir']},
... ) ... )
......
...@@ -20,7 +20,7 @@ testing repository. ...@@ -20,7 +20,7 @@ testing repository.
Turn on logging on this server so that we can see when eggs are pulled Turn on logging on this server so that we can see when eggs are pulled
from it. from it.
>>> get(link_server2 + 'enable_server_logging') >>> get(link_server2 + 'enable_server_logging')
GET 200 /enable_server_logging GET 200 /enable_server_logging
'' ''
...@@ -83,10 +83,9 @@ buildout to see where the egg comes from this time. ...@@ -83,10 +83,9 @@ buildout to see where the egg comes from this time.
... for egg in glob(join(sample_buildout, 'eggs', 'demoneeded*.egg')): ... for egg in glob(join(sample_buildout, 'eggs', 'demoneeded*.egg')):
... remove(sample_buildout, 'eggs', egg) ... remove(sample_buildout, 'eggs', egg)
>>> remove_demoneeded_egg() >>> remove_demoneeded_egg()
>>> print system(buildout) >>> print system(buildout) # doctest: +ELLIPSIS
Develop: '/sample-buildout/depdemo' Develop: '/sample-buildout/depdemo'
Updating eggs. ...
Couldn't find index page for 'demoneeded' (maybe misspelled?)
Getting distribution for 'demoneeded'. Getting distribution for 'demoneeded'.
While: While:
Updating eggs. Updating eggs.
......
This diff is collapsed.
...@@ -1277,6 +1277,7 @@ this is very straightforward. ...@@ -1277,6 +1277,7 @@ this is very straightforward.
"""Add site packages, as determined by zc.buildout. """Add site packages, as determined by zc.buildout.
<BLANKLINE> <BLANKLINE>
See original_addsitepackages, below, for the original version.""" See original_addsitepackages, below, for the original version."""
setuptools_path = None
buildout_paths = [ buildout_paths = [
'/interpreter/eggs/demo-0.3-pyN.N.egg', '/interpreter/eggs/demo-0.3-pyN.N.egg',
'/interpreter/eggs/demoneeded-1.1-pyN.N.egg' '/interpreter/eggs/demoneeded-1.1-pyN.N.egg'
...@@ -1291,7 +1292,8 @@ this is very straightforward. ...@@ -1291,7 +1292,8 @@ this is very straightforward.
... ...
] ]
for path in original_paths: for path in original_paths:
addsitedir(path, known_paths) if path == setuptools_path or path not in known_paths:
addsitedir(path, known_paths)
return known_paths return known_paths
<BLANKLINE> <BLANKLINE>
def original_addsitepackages(known_paths):... def original_addsitepackages(known_paths):...
...@@ -1368,7 +1370,8 @@ call to another text fixture to create. ...@@ -1368,7 +1370,8 @@ call to another text fixture to create.
... ...
] ]
for path in original_paths: for path in original_paths:
addsitedir(path, known_paths) if path == setuptools_path or path not in known_paths:
addsitedir(path, known_paths)
return known_paths return known_paths
<BLANKLINE> <BLANKLINE>
def original_addsitepackages(known_paths):... def original_addsitepackages(known_paths):...
...@@ -1432,7 +1435,8 @@ at that result. ...@@ -1432,7 +1435,8 @@ at that result.
... ...
] ]
for path in original_paths: for path in original_paths:
addsitedir(path, known_paths) if path == setuptools_path or path not in known_paths:
addsitedir(path, known_paths)
return known_paths return known_paths
<BLANKLINE> <BLANKLINE>
def original_addsitepackages(known_paths):... def original_addsitepackages(known_paths):...
......
...@@ -596,7 +596,7 @@ else: ...@@ -596,7 +596,7 @@ else:
sep = re.escape(os.path.sep) 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=sep)),
_normalize_path, _normalize_path,
) )
......
...@@ -15,7 +15,7 @@ The handers before calling set up are: ...@@ -15,7 +15,7 @@ The handers before calling set up are:
>>> len(logging.getLogger().handlers) >>> len(logging.getLogger().handlers)
1 1
>>> logging.getLogger().handlers # doctest: +ELLIPSIS >>> logging.getLogger().handlers # doctest: +ELLIPSIS
[<zope.testrunner.logsupport.NullHandler instance at ...>] [<zope...testrunner.logsupport.NullHandler instance at ...>]
After calling it, a ``logging.StreamHandler`` was added: After calling it, a ``logging.StreamHandler`` was added:
...@@ -27,7 +27,7 @@ After calling it, a ``logging.StreamHandler`` was added: ...@@ -27,7 +27,7 @@ After calling it, a ``logging.StreamHandler`` was added:
>>> len(logging.getLogger().handlers) >>> len(logging.getLogger().handlers)
2 2
>>> logging.getLogger().handlers # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE >>> logging.getLogger().handlers # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
[<zope.testrunner.logsupport.NullHandler instance at ...>, [<zope...testrunner.logsupport.NullHandler instance at ...>,
<logging.StreamHandler instance at ...>] <logging.StreamHandler instance at ...>]
But tear down removes the new logging handler: But tear down removes the new logging handler:
...@@ -36,4 +36,4 @@ But tear down removes the new logging handler: ...@@ -36,4 +36,4 @@ But tear down removes the new logging handler:
>>> len(logging.getLogger().handlers) >>> len(logging.getLogger().handlers)
1 1
>>> logging.getLogger().handlers # doctest: +ELLIPSIS >>> logging.getLogger().handlers # doctest: +ELLIPSIS
[<zope.testrunner.logsupport.NullHandler instance at ...>] [<zope...testrunner.logsupport.NullHandler instance at ...>]
This diff is collapsed.
...@@ -3,13 +3,14 @@ Automatic Buildout Updates ...@@ -3,13 +3,14 @@ Automatic Buildout Updates
When a buildout is run, one of the first steps performed is to check When a buildout is run, one of the first steps performed is to check
for updates to either zc.buildout or setuptools. To demonstrate this, for updates to either zc.buildout or setuptools. To demonstrate this,
we've creates some "new releases" of buildout and setuptools in a we've created some "new releases" of buildout and setuptools in a
new_releases folder: new_releases folder:
>>> ls(new_releases) >>> ls(new_releases)
d setuptools d setuptools
- setuptools-99.99-py2.4.egg - setuptools-99.99-py2.4.egg
d zc.buildout d zc.buildout
- zc.buildout-100.0b1-pyN.N.egg
- zc.buildout-99.99-py2.4.egg - zc.buildout-99.99-py2.4.egg
Let's update the sample buildout.cfg to look in this area: Let's update the sample buildout.cfg to look in this area:
...@@ -78,6 +79,13 @@ new versions found in new releases: ...@@ -78,6 +79,13 @@ new versions found in new releases:
zc.buildout 99.99 zc.buildout 99.99
setuptools 99.99 setuptools 99.99
Notice that, even though we have a newer beta version of zc.buildout
available, the final "99.99" was selected. If you want to get non-final
versions, specify a specific version in your buildout's versions
section, you typically want to use the --accept-buildout-test-releases
option to the bootstrap script, which internally uses the
``accept-buildout-test-releases = true`` discussed below.
Our buildout script's site.py has been updated to use the new eggs: Our buildout script's site.py has been updated to use the new eggs:
>>> cat(sample_buildout, 'parts', 'buildout', 'site.py') >>> cat(sample_buildout, 'parts', 'buildout', 'site.py')
...@@ -162,7 +170,7 @@ Or in non-newest mode: ...@@ -162,7 +170,7 @@ Or in non-newest mode:
setuptools 0.6 setuptools 0.6
We also won't upgrade if the buildout script being run isn't in the We also won't upgrade if the buildout script being run isn't in the
buildouts bin directory. To see this we'll create a new buildout buildout's bin directory. To see this we'll create a new buildout
directory: directory:
>>> sample_buildout2 = tmpdir('sample_buildout2') >>> sample_buildout2 = tmpdir('sample_buildout2')
...@@ -187,3 +195,57 @@ directory: ...@@ -187,3 +195,57 @@ directory:
Not upgrading because not running a local buildout command. Not upgrading because not running a local buildout command.
>>> ls('bin') >>> ls('bin')
As mentioned above, the ``accept-buildout-test-releases = true`` means that
newer non-final versions of these dependencies are preferred. Typically
users are not expected to actually manipulate this value. Instead, the
bootstrap script creates a buildout buildout script that passes in the
value as a command line override. This then results in the buildout
script being rewritten to remember the decision.
We'll mimic this by passing the argument actually in the command line.
>>> cd(sample_buildout)
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... find-links = %(new_releases)s
... index = %(new_releases)s
... parts = show-versions
... develop = showversions
...
... [show-versions]
... recipe = showversions
... """ % dict(new_releases=new_releases))
>>> print system(buildout +
... ' buildout:accept-buildout-test-releases=true'),
... # doctest: +NORMALIZE_WHITESPACE
Getting distribution for 'zc.buildout'.
Got zc.buildout 100.0b1.
Upgraded:
zc.buildout version 100.0b1,
setuptools version 99.99;
restarting.
Generated script '/sample-buildout/bin/buildout'.
NOTE: Accepting early releases of build system packages. Rerun bootstrap
without --accept-buildout-test-releases (-t) to return to default
behavior.
Develop: '/sample-buildout/showversions'
Updating show-versions.
zc.buildout 100.0b1
setuptools 99.99
The buildout script shows the change.
>>> buildout_script = join(sample_buildout, 'bin', 'buildout')
>>> import sys
>>> if sys.platform.startswith('win'):
... buildout_script += '-script.py'
>>> print open(buildout_script).read() # doctest: +ELLIPSIS
#...
sys.argv.insert(1, 'buildout:accept-buildout-test-releases=true')
print ('NOTE: Accepting early releases of build system packages. Rerun '
'bootstrap without --accept-buildout-test-releases (-t) to return to '
'default behavior.')
...
Version 1.5.0 of buildout (and higher) provides the ability to use
buildout directly with a system Python if you use z3c.recipe.scripts or
other isolation-aware recipes that use the sitepackage_safe_scripts function.
Some people use virtualenv to provide similar functionality.
Unfortunately, a problem with the virtualenv executable as of this
writing means that -S will not work properly with it (see
https://bugs.launchpad.net/virtualenv/+bug/572545). This breaks
buildout's approach to providing isolation.
Because of this, if buildout detects an executable with a broken -S
option, it will revert to its pre-1.5.0 behavior. If buildout has been
asked to provide isolation, it will warn the user that isolation will
not be provided by buildout, but proceed. This should give full
backwards compatibility to virtualenv users.
The only minor annoyance in the future may be recipes that explicitly
use the new buildout functionality to provide isolation: as described
above, the builds will proceed, but users will receive warnings that
buildout is not providing isolation itself. The warnings themselves can
be squelched when running bin/buildout with the ``-s`` option or with a
lower verbosity than usual (e.g., one or more ``-q`` options).
For tests, then, we can examine several things. We'll focus on four.
- Running bootstrap with an executable broken in this way will not try to do
any -S tricks.
- Running sitepackage_safe_scripts with a virtualenv will create an
old-style script. This will affect the bin/buildout script that is
created, for instance. If the sitepackage_safe_scripts function is asked
to provide isolation under these circumstances, it will warn that isolation
will not be available, but still create the desired script.
- Using the easy_install Installer or install or build functions and trying
to request isolation will generate a warning and then the isolation request
will be ignored as it proceeds.
- Passing -s (or -q) to the bin/buildout script will squelch warnings.
Testing these involves first creating a Python that exhibits the same
behavior as the problematic one we care about from virtualenv. Let's do that
first.
>>> import os, sys
>>> from zc.buildout.easy_install import _safe_arg
>>> py_path, site_packages_path = make_py()
>>> if sys.platform == 'win32':
... py_script_path = py_path + '-script.py'
... else:
... py_script_path = py_path
...
>>> py_file = open(py_script_path)
>>> py_lines = py_file.readlines()
>>> py_file.close()
>>> py_file = open(py_script_path, 'w')
>>> extra = '''\
... new_argv = argv[:1]
... for ix, val in enumerate(argv[1:]):
... if val.startswith('--'):
... new_argv.append(val)
... if val.startswith('-') and len(val) > 1:
... if 'S' in val:
... val = val.replace('S', '')
... environ['BROKEN_DASH_S'] = 'Y'
... if val != '-':
... new_argv.append(val)
... if 'c' in val:
... new_argv.extend(argv[ix+2:])
... break
... else:
... new_argv.extend(argv[ix+1:])
... argv = new_argv
... '''
>>> for line in py_lines:
... py_file.write(line)
... if line.startswith('environ = os.environ.copy()'):
... py_file.write(extra)
... print 'Rewritten.'
...
Rewritten.
>>> py_file.close()
>>> sitecustomize_path = join(os.path.dirname(site_packages_path),
... 'parts', 'py', 'sitecustomize.py')
>>> sitecustomize_file = open(sitecustomize_path, 'a')
>>> sitecustomize_file.write('''
... import os, sys
... sys.executable = %r
... if 'BROKEN_DASH_S' in os.environ:
... class ImportHook:
... site = None
...
... @classmethod
... def find_module(klass, fullname, path=None):
... if klass.site is None and 'site' in sys.modules:
... # Pop site out of sys.modules. This will be a
... # close-enough approximation of site not being
... # loaded for our tests--it lets us provoke the
... # right errors when the fixes are absent, and
... # works well enough when the fixes are present.
... klass.site = sys.modules.pop('site')
... if fullname == 'ConfigParser':
... raise ImportError(fullname)
... elif fullname == 'site':
... # Keep the site module from being processed twice.
... return klass
...
... @classmethod
... def load_module(klass, fullname):
... if fullname == 'site':
... return klass.site
... raise ImportError(fullname)
...
... sys.meta_path.append(ImportHook)
... ''' % (py_path,))
>>> sitecustomize_file.close()
>>> print call_py(
... _safe_arg(py_path),
... "import ConfigParser")
<BLANKLINE>
>>> print 'X'; print call_py(
... _safe_arg(py_path),
... "import ConfigParser",
... '-S') # doctest: +ELLIPSIS
X...Traceback (most recent call last):
...
ImportError: No module named ConfigParser
<BLANKLINE>
>>> from zc.buildout.easy_install import _has_broken_dash_S
>>> _has_broken_dash_S(py_path)
True
Well, that was ugly, but it seems to have done the trick. The
executable represented by py_path has the same problematic
characteristic as the virtualenv one: -S results in a Python that does
not allow the import of some packages from the standard library. We'll
test with this.
First, let's try running bootstrap.
>>> from os.path import dirname, join
>>> import zc.buildout
>>> bootstrap_py = join(
... dirname(
... dirname(
... dirname(
... dirname(zc.buildout.__file__)
... )
... )
... ),
... 'bootstrap', 'bootstrap.py')
>>> broken_S_buildout = tmpdir('broken_S')
>>> os.chdir(broken_S_buildout)
>>> write('buildout.cfg',
... '''
... [buildout]
... parts =
... ''')
>>> write('bootstrap.py', open(bootstrap_py).read())
>>> print 'X'; print system(
... _safe_arg(py_path)+' '+
... 'bootstrap.py'); print 'X' # doctest: +ELLIPSIS
X...
Generated script '/broken_S/bin/buildout'.
...
If bootstrap didn't look out for a broken -S, that would have failed. Moreover,
take a look at bin/buildout:
>>> cat('bin', 'buildout')
#!/executable_buildout/bin/py
<BLANKLINE>
import sys
sys.path[0:0] = [
'/broken_S/eggs/setuptools-0.0-pyN.N.egg',
'/broken_S/eggs/zc.buildout-0.0-pyN.N.egg',
]
<BLANKLINE>
import zc.buildout.buildout
<BLANKLINE>
if __name__ == '__main__':
zc.buildout.buildout.main()
That's the old-style buildout script: no changes for users with this issue.
Of course, they don't get the new features either, presumably because
they don't need or want them. This means that if they use a recipe that
tries to use a new feature, the behavior needs to degrade gracefully.
Here's an example. We'll switch to another buildout in which it is easier to
use local dev versions of zc.buildout and z3c.recipe.scripts.
>>> os.chdir(dirname(dirname(buildout)))
>>> write('buildout.cfg',
... '''
... [buildout]
... parts = eggs
... find-links = %(link_server)s
...
... [primed_python]
... executable = %(py_path)s
...
... [eggs]
... recipe = z3c.recipe.scripts
... python = primed_python
... interpreter = py
... eggs = demo
... ''' % globals())
>>> print system(buildout) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
Installing eggs.
Getting distribution for 'demo'.
Got demo 0.4c1.
Getting distribution for 'demoneeded'.
Got demoneeded 1.2c1.
Generated script '/sample-buildout/bin/demo'.
Generated interpreter '/sample-buildout/bin/py'.
...UserWarning: Buildout has been asked to exclude or limit site-packages
so that builds can be repeatable when using a system Python. However,
the chosen Python executable has a broken implementation of -S (see
https://bugs.launchpad.net/virtualenv/+bug/572545 for an example
problem) and this breaks buildout's ability to isolate site-packages.
If the executable already has a clean site-packages (e.g., using
virtualenv's ``--no-site-packages`` option) you may be getting
equivalent repeatability. To silence this warning, use the -s argument
to the buildout script. Alternatively, use a Python executable with a
working -S (such as a standard Python binary).
warnings.warn(BROKEN_DASH_S_WARNING)
<BLANKLINE>
So, it did what we asked as best it could, but gave a big warning. If
you don't want those warnings for those particular recipes that use the
new features, you can use the "-s" option to squelch the warnings.
>>> print system(buildout + ' -s')
Updating eggs.
<BLANKLINE>
A lower verbosity (one or more -q options) also quiets the warning.
>>> print system(buildout + ' -q')
<BLANKLINE>
Notice that, as we saw before with bin/buildout, the generated scripts
are old-style, because the new-style feature gracefully degrades to the
previous implementation when it encounters an executable with a broken
dash-S.
>>> print 'X'; cat('bin', 'py') # doctest: +ELLIPSIS
X...
<BLANKLINE>
import sys
<BLANKLINE>
sys.path[0:0] = [
'/sample-buildout/eggs/demo-0.4c1-pyN.N.egg',
'/sample-buildout/eggs/demoneeded-1.2c1-pyN.N.egg',
]
...
Change History Change History
************** **************
1.0.0 (unreleased)
==================
(no significant changes)
1.0.0b1 (2010-04-29) 1.0.0b1 (2010-04-29)
==================== ====================
......
include *.txt
recursive-include src *.txt
exclude MANIFEST.in buildout.cfg .bzrignore
...@@ -12,11 +12,9 @@ ...@@ -12,11 +12,9 @@
# #
############################################################################## ##############################################################################
"""Setup for z3c.recipe.scripts package """Setup for z3c.recipe.scripts package
$Id: setup.py 106736 2009-12-18 02:33:08Z gary $
""" """
version = '1.0.0dev' version = '1.0.0'
import os import os
from setuptools import setup, find_packages from setuptools import setup, find_packages
...@@ -60,8 +58,8 @@ setup( ...@@ -60,8 +58,8 @@ setup(
package_dir = {'':'src'}, package_dir = {'':'src'},
namespace_packages = ['z3c', 'z3c.recipe'], namespace_packages = ['z3c', 'z3c.recipe'],
install_requires = [ install_requires = [
'zc.buildout >=1.5.0dev', 'zc.buildout >=1.5.0',
'zc.recipe.egg >=1.2.3dev', 'zc.recipe.egg >=1.3.0',
'setuptools'], 'setuptools'],
tests_require = ['zope.testing'], tests_require = ['zope.testing'],
test_suite = name+'.tests.test_suite', test_suite = name+'.tests.test_suite',
......
...@@ -35,23 +35,13 @@ class Base(ScriptBase): ...@@ -35,23 +35,13 @@ class Base(ScriptBase):
'*') '*')
self.allowed_eggs = tuple(name.strip() for name in value.split('\n')) self.allowed_eggs = tuple(name.strip() for name in value.split('\n'))
value = options.setdefault( self.include_site_packages = options.query_bool(
'include-site-packages', 'include-site-packages',
b_options.get('include-site-packages', 'false')) default=b_options.get('include-site-packages', 'false'))
if value not in ('true', 'false'):
raise zc.buildout.UserError(
"Invalid value for include-site-packages option: %s" %
(value,))
self.include_site_packages = (value == 'true')
value = options.setdefault( self.exec_sitecustomize = options.query_bool(
'exec-sitecustomize', 'exec-sitecustomize',
b_options.get('exec-sitecustomize', 'false')) default=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): class Interpreter(Base):
......
...@@ -416,24 +416,26 @@ def test_suite(): ...@@ -416,24 +416,26 @@ def test_suite():
'README.txt', 'README.txt',
setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown, setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([ checker=renormalizing.RENormalizing([
zc.buildout.testing.normalize_path, zc.buildout.testing.normalize_path,
zc.buildout.testing.normalize_endings, zc.buildout.testing.normalize_endings,
zc.buildout.testing.normalize_script, zc.buildout.testing.normalize_script,
zc.buildout.testing.normalize_egg_py, zc.buildout.testing.normalize_egg_py,
zc.buildout.tests.normalize_bang, zc.buildout.tests.normalize_bang,
(re.compile(r'zc.buildout(-\S+)?[.]egg(-link)?'), zc.buildout.tests.hide_distribute_additions,
'zc.buildout.egg'), zc.buildout.tests.hide_first_index_page_message,
(re.compile('[-d] (setuptools|distribute)-[^-]+-'), 'setuptools-X-'), (re.compile(r'zc.buildout(-\S+)?[.]egg(-link)?'),
(re.compile(r'(setuptools|distribute)-[\w.]+-py'), 'setuptools-X-py'), 'zc.buildout.egg'),
(re.compile(r'eggs\\\\demo'), 'eggs/demo'), (re.compile('[-d] (setuptools|distribute)-[^-]+-'), 'setuptools-X-'),
(re.compile(r'[a-zA-Z]:\\\\foo\\\\bar'), '/foo/bar'), (re.compile(r'(setuptools|distribute)-[\w.]+-py'), 'setuptools-X-py'),
(re.compile(r'\#!\S+\bpython\S*'), '#!/usr/bin/python'), (re.compile(r'eggs\\\\demo'), 'eggs/demo'),
# Normalize generate_script's Windows interpreter to UNIX: (re.compile(r'[a-zA-Z]:\\\\foo\\\\bar'), '/foo/bar'),
(re.compile(r'\nimport subprocess\n'), '\n'), (re.compile(r'\#!\S+\bpython\S*'), '#!/usr/bin/python'),
(re.compile('subprocess\\.call\\(argv, env=environ\\)'), # Normalize generate_script's Windows interpreter to UNIX:
'os.execve(sys.executable, argv, environ)'), (re.compile(r'\nimport subprocess\n'), '\n'),
(re.compile('distribute'), 'setuptools'), (re.compile('subprocess\\.call\\(argv, env=environ\\)'),
]) 'os.execve(sys.executable, argv, environ)'),
(re.compile('distribute'), 'setuptools'),
])
), ),
doctest.DocTestSuite( doctest.DocTestSuite(
setUp=setUp, setUp=setUp,
...@@ -442,6 +444,8 @@ def test_suite(): ...@@ -442,6 +444,8 @@ def test_suite():
zc.buildout.testing.normalize_path, zc.buildout.testing.normalize_path,
zc.buildout.testing.normalize_endings, zc.buildout.testing.normalize_endings,
zc.buildout.testing.normalize_egg_py, zc.buildout.testing.normalize_egg_py,
zc.buildout.tests.hide_distribute_additions,
zc.buildout.tests.hide_first_index_page_message,
(re.compile(r'[a-zA-Z]:\\\\foo\\\\bar'), '/foo/bar'), (re.compile(r'[a-zA-Z]:\\\\foo\\\\bar'), '/foo/bar'),
]), ]),
), ),
......
Change History Change History
************** **************
1.3.0 (unreleased)
==================
- Small further refactorings past 1.2.3b1 to be compatible with zc.buildout
1.5.0.
1.2.3b1 (2010-04-29) 1.2.3b1 (2010-04-29)
==================== ====================
......
include *.txt
recursive-include src *.txt
exclude MANIFEST.in buildout.cfg .bzrignore
...@@ -12,11 +12,9 @@ ...@@ -12,11 +12,9 @@
# #
############################################################################## ##############################################################################
"""Setup for zc.recipe.egg package """Setup for zc.recipe.egg package
$Id$
""" """
version = '1.2.3dev' version = '1.3.0'
import os import os
from setuptools import setup, find_packages from setuptools import setup, find_packages
...@@ -66,7 +64,7 @@ setup( ...@@ -66,7 +64,7 @@ setup(
package_dir = {'':'src'}, package_dir = {'':'src'},
namespace_packages = ['zc', 'zc.recipe'], namespace_packages = ['zc', 'zc.recipe'],
install_requires = [ install_requires = [
'zc.buildout >=1.5.0dev', 'zc.buildout >=1.5.0',
'setuptools'], 'setuptools'],
tests_require = ['zope.testing'], tests_require = ['zope.testing'],
test_suite = name+'.tests.test_suite', test_suite = name+'.tests.test_suite',
......
...@@ -52,9 +52,6 @@ class Eggs(object): ...@@ -52,9 +52,6 @@ class Eggs(object):
options['develop-eggs-directory'] = b_options['develop-eggs-directory'] options['develop-eggs-directory'] = b_options['develop-eggs-directory']
options['_d'] = options['develop-eggs-directory'] # backward compat. options['_d'] = options['develop-eggs-directory'] # backward compat.
# verify that this is None, 'true' or 'false'
get_bool(options, 'unzip')
python = options.setdefault('python', b_options['python']) python = options.setdefault('python', b_options['python'])
options['executable'] = buildout[python]['executable'] options['executable'] = buildout[python]['executable']
...@@ -84,7 +81,7 @@ class Eggs(object): ...@@ -84,7 +81,7 @@ class Eggs(object):
else: else:
kw = {} kw = {}
if 'unzip' in options: if 'unzip' in options:
kw['always_unzip'] = get_bool(options, 'unzip') kw['always_unzip'] = options.query_bool('unzip', None)
ws = zc.buildout.easy_install.install( ws = zc.buildout.easy_install.install(
distributions, options['eggs-directory'], distributions, options['eggs-directory'],
links=self.links, links=self.links,
...@@ -159,7 +156,7 @@ class ScriptBase(Eggs): ...@@ -159,7 +156,7 @@ class ScriptBase(Eggs):
raise zc.buildout.UserError("Invalid entry point") raise zc.buildout.UserError("Invalid entry point")
reqs.append(parsed.groups()) reqs.append(parsed.groups())
if get_bool(options, 'dependent-scripts'): if options.query_bool('dependent-scripts', 'false'):
# Generate scripts for all packages in the working set, # Generate scripts for all packages in the working set,
# except setuptools. # except setuptools.
reqs = list(reqs) reqs = list(reqs)
...@@ -192,17 +189,4 @@ class Scripts(ScriptBase): ...@@ -192,17 +189,4 @@ class Scripts(ScriptBase):
relative_paths=self._relative_paths relative_paths=self._relative_paths
) )
def get_bool(options, name, default=False):
value = options.get(name)
if not value:
return default
if value == 'true':
return True
elif value == 'false':
return False
else:
raise zc.buildout.UserError(
"Invalid value for %s option: %s" % (name, value))
Egg = Scripts Egg = Scripts
...@@ -43,54 +43,58 @@ def test_suite(): ...@@ -43,54 +43,58 @@ def test_suite():
'README.txt', 'README.txt',
setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown, setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([ checker=renormalizing.RENormalizing([
zc.buildout.testing.normalize_path, zc.buildout.testing.normalize_path,
zc.buildout.testing.normalize_endings, zc.buildout.testing.normalize_endings,
zc.buildout.testing.normalize_script, zc.buildout.testing.normalize_script,
zc.buildout.testing.normalize_egg_py, zc.buildout.testing.normalize_egg_py,
zc.buildout.tests.normalize_bang, zc.buildout.tests.normalize_bang,
(re.compile('zc.buildout(-\S+)?[.]egg(-link)?'), zc.buildout.tests.hide_distribute_additions,
'zc.buildout.egg'), (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'),
(re.compile('[-d] (setuptools|distribute)-[^-]+-'), 'zc.buildout.egg'),
'setuptools-X-'), (re.compile('[-d] (setuptools|distribute)-[^-]+-'),
(re.compile(r'eggs\\\\demo'), 'eggs/demo'), 'setuptools-X-'),
(re.compile(r'[a-zA-Z]:\\\\foo\\\\bar'), '/foo/bar'), (re.compile(r'eggs\\\\demo'), 'eggs/demo'),
# Distribute unzips eggs by default. (re.compile(r'[a-zA-Z]:\\\\foo\\\\bar'), '/foo/bar'),
(re.compile('\- demoneeded'), 'd demoneeded'), # Distribute unzips eggs by default.
]) (re.compile('\- demoneeded'), 'd demoneeded'),
])
), ),
doctest.DocFileSuite( doctest.DocFileSuite(
'api.txt', 'api.txt',
setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown, setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([ checker=renormalizing.RENormalizing([
zc.buildout.testing.normalize_path, zc.buildout.testing.normalize_path,
zc.buildout.testing.normalize_endings, zc.buildout.testing.normalize_endings,
(re.compile('__buildout_signature__ = ' zc.buildout.tests.hide_distribute_additions,
'sample-\S+\s+' (re.compile('__buildout_signature__ = '
'zc.recipe.egg-\S+\s+' 'sample-\S+\s+'
'(setuptools|distribute)-\S+\s+' 'zc.recipe.egg-\S+\s+'
'zc.buildout-\S+\s*' '(setuptools|distribute)-\S+\s+'
), 'zc.buildout-\S+\s*'
'__buildout_signature__ = sample- zc.recipe.egg-\n'), ),
(re.compile('executable = [\S ]+python\S*', re.I), '__buildout_signature__ = sample- zc.recipe.egg-\n'),
'executable = python'), (re.compile('executable = [\S ]+python\S*', re.I),
(re.compile('find-links = http://localhost:\d+/'), 'executable = python'),
'find-links = http://localhost:8080/'), (re.compile('find-links = http://localhost:\d+/'),
(re.compile('index = http://localhost:\d+/index'), 'find-links = http://localhost:8080/'),
'index = http://localhost:8080/index'), (re.compile('index = http://localhost:\d+/index'),
]) 'index = http://localhost:8080/index'),
])
), ),
doctest.DocFileSuite( doctest.DocFileSuite(
'custom.txt', 'custom.txt',
setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown, setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([ checker=renormalizing.RENormalizing([
zc.buildout.testing.normalize_path, zc.buildout.testing.normalize_path,
zc.buildout.testing.normalize_endings, zc.buildout.testing.normalize_endings,
(re.compile("(d ((ext)?demo(needed)?|other)" zc.buildout.tests.hide_distribute_additions,
"-\d[.]\d-py)\d[.]\d(-\S+)?[.]egg"), zc.buildout.tests.hide_zip_safe_message,
'\\1V.V.egg'), (re.compile("(d ((ext)?demo(needed)?|other)"
(re.compile('extdemo.c\n.+\\extdemo.exp\n'), ''), "-\d[.]\d-py)\d[.]\d(-\S+)?[.]egg"),
(re.compile('extdemo[.]pyd'), 'extdemo.so') '\\1V.V.egg'),
]), (re.compile('extdemo.c\n.+\\extdemo.exp\n'), ''),
(re.compile('extdemo[.]pyd'), 'extdemo.so')
]),
), ),
)) ))
...@@ -104,21 +108,22 @@ def test_suite(): ...@@ -104,21 +108,22 @@ def test_suite():
setUp=setUpSelecting, setUp=setUpSelecting,
tearDown=zc.buildout.testing.buildoutTearDown, tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([ checker=renormalizing.RENormalizing([
zc.buildout.testing.normalize_path, zc.buildout.testing.normalize_path,
zc.buildout.testing.normalize_endings, zc.buildout.testing.normalize_endings,
zc.buildout.testing.normalize_script, zc.buildout.testing.normalize_script,
(re.compile('Got (setuptools|distribute) \S+'), zc.buildout.tests.hide_distribute_additions,
'Got setuptools V'), (re.compile('Got (setuptools|distribute) \S+'),
(re.compile('([d-] )?(setuptools|distribute)-\S+-py'), 'Got setuptools V'),
'setuptools-V-py'), (re.compile('([d-] )?(setuptools|distribute)-\S+-py'),
(re.compile('-py2[.][0-35-9][.]'), 'py2.5.'), 'setuptools-V-py'),
(re.compile('zc.buildout-\S+[.]egg'), (re.compile('-py2[.][0-35-9][.]'), 'py2.5.'),
'zc.buildout.egg'), (re.compile('zc.buildout-\S+[.]egg'),
(re.compile('zc.buildout[.]egg-link'), 'zc.buildout.egg'),
'zc.buildout.egg'), (re.compile('zc.buildout[.]egg-link'),
# Distribute unzips eggs by default. 'zc.buildout.egg'),
(re.compile('\- demoneeded'), 'd demoneeded'), # Distribute unzips eggs by default.
]), (re.compile('\- demoneeded'), 'd demoneeded'),
]),
), ),
) )
......
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