[Checkins] SVN: zc.buildout/trunk/ merge of svn+ssh://svn.zope.org/repos/main/zc.buildout/branches/gary-betafix r115885

Gary Poster gary.poster at canonical.com
Mon Aug 23 11:04:24 EDT 2010


Log message for revision 115887:
  merge of svn+ssh://svn.zope.org/repos/main/zc.buildout/branches/gary-betafix r115885

Changed:
  _U  zc.buildout/trunk/
  U   zc.buildout/trunk/CHANGES.txt
  A   zc.buildout/trunk/MANIFEST.in
  A   zc.buildout/trunk/SYSTEM_PYTHON_HELP.txt
  D   zc.buildout/trunk/bootstrap/bootstrap.py
  A   zc.buildout/trunk/bootstrap/bootstrap.py
  D   zc.buildout/trunk/bootstrap/newbootstrap.py
  U   zc.buildout/trunk/buildout.cfg
  U   zc.buildout/trunk/dev.py
  U   zc.buildout/trunk/setup.py
  U   zc.buildout/trunk/src/zc/buildout/allowhosts.txt
  U   zc.buildout/trunk/src/zc/buildout/bootstrap.txt
  U   zc.buildout/trunk/src/zc/buildout/buildout.py
  U   zc.buildout/trunk/src/zc/buildout/buildout.txt
  U   zc.buildout/trunk/src/zc/buildout/debugging.txt
  U   zc.buildout/trunk/src/zc/buildout/dependencylinks.txt
  U   zc.buildout/trunk/src/zc/buildout/easy_install.py
  U   zc.buildout/trunk/src/zc/buildout/easy_install.txt
  U   zc.buildout/trunk/src/zc/buildout/testing.py
  U   zc.buildout/trunk/src/zc/buildout/testing_bugfix.txt
  U   zc.buildout/trunk/src/zc/buildout/tests.py
  U   zc.buildout/trunk/src/zc/buildout/testselectingpython.py
  U   zc.buildout/trunk/src/zc/buildout/update.txt
  A   zc.buildout/trunk/src/zc/buildout/virtualenv.txt
  U   zc.buildout/trunk/z3c.recipe.scripts_/CHANGES.txt
  A   zc.buildout/trunk/z3c.recipe.scripts_/MANIFEST.in
  U   zc.buildout/trunk/z3c.recipe.scripts_/setup.py
  U   zc.buildout/trunk/z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py
  U   zc.buildout/trunk/z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py
  U   zc.buildout/trunk/zc.recipe.egg_/CHANGES.txt
  A   zc.buildout/trunk/zc.recipe.egg_/MANIFEST.in
  U   zc.buildout/trunk/zc.recipe.egg_/setup.py
  U   zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/egg.py
  U   zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/tests.py

-=-

Property changes on: zc.buildout/trunk
___________________________________________________________________
Modified: svn:mergeinfo
   - /zc.buildout/branches/gary-launchpad:111587
/zc.buildout/trunk:108946

   + /zc.buildout/branches/gary-launchpad:111587
/zc.buildout/branches/gary-betafix:115514,115815,115845-115847,115859
/zc.buildout/trunk:108946

Modified: svk:merge
   - 62d5b8a3-27da-0310-9561-8e5933582275:/zc.buildout/branches/gary-launchpad:111587
62d5b8a3-27da-0310-9561-8e5933582275:/zc.buildout/trunk:108946

   + 62d5b8a3-27da-0310-9561-8e5933582275:/zc.buildout/branches/gary-betafix:115859
62d5b8a3-27da-0310-9561-8e5933582275:/zc.buildout/branches/gary-launchpad:111587
62d5b8a3-27da-0310-9561-8e5933582275:/zc.buildout/trunk:108946


Modified: zc.buildout/trunk/CHANGES.txt
===================================================================
--- zc.buildout/trunk/CHANGES.txt	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/CHANGES.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -1,6 +1,42 @@
 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)
 ====================
 
@@ -10,8 +46,13 @@
   both from command line and from config files. (gotcha)
 
 - 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
-  recipe to generate scripts and interpreters, rather than zc.recipe.egg.
+  in site-packages), as long as you use (1) A fresh checkout, (2) the
+  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
   generating scripts and interpreters if you are using a "clean" Python,
@@ -42,15 +83,15 @@
   * The buildout script generated by bootstrap honors more of the settings
     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).
     https://bugs.launchpad.net/zc.buildout/+bug/410528
 
 - You can develop zc.buildout using Distribute instead of Setuptools.  Use
   the --distribute option on the dev.py script.  (Releases should be tested
   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
-  Python 2.5 and 2.6.  Using zc.buildout with Distribute and Python 2.4
+  with Setuptools and Python 2.4, 2.5, 2.6, and 2.7; and with Distribute and
+  Python 2.5, 2.6, and 2.7.  Using zc.buildout with Distribute and Python 2.4
   is not recommended.
 
 - The ``distribute-version`` now works in the [buildout] section, mirroring

Copied: zc.buildout/trunk/MANIFEST.in (from rev 115859, zc.buildout/branches/gary-betafix/MANIFEST.in)
===================================================================
--- zc.buildout/trunk/MANIFEST.in	                        (rev 0)
+++ zc.buildout/trunk/MANIFEST.in	2010-08-23 15:04:24 UTC (rev 115887)
@@ -0,0 +1,3 @@
+include *.txt
+recursive-include src *.txt
+exclude MANIFEST.in buildout.cfg .bzrignore

Copied: zc.buildout/trunk/SYSTEM_PYTHON_HELP.txt (from rev 115859, zc.buildout/branches/gary-betafix/SYSTEM_PYTHON_HELP.txt)
===================================================================
--- zc.buildout/trunk/SYSTEM_PYTHON_HELP.txt	                        (rev 0)
+++ zc.buildout/trunk/SYSTEM_PYTHON_HELP.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -0,0 +1,226 @@
+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.

Deleted: zc.buildout/trunk/bootstrap/bootstrap.py
===================================================================
--- zc.buildout/trunk/bootstrap/bootstrap.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/bootstrap/bootstrap.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -1,116 +0,0 @@
-##############################################################################
-#
-# 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, urllib2
-from optparse import OptionParser
-
-tmpeggs = tempfile.mkdtemp()
-
-is_jython = sys.platform.startswith('java')
-
-# parsing arguments
-parser = OptionParser()
-parser.add_option("-v", "--version", dest="version",
-                          help="use a specific zc.buildout version")
-parser.add_option("-d", "--distribute",
-                   action="store_true", dest="distribute", default=False,
-                   help="Use Distribute rather than Setuptools.")
-
-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.version is not None:
-    VERSION = '==%s' % options.version
-else:
-    VERSION = ''
-
-USE_DISTRIBUTE = options.distribute
-args = args + ['bootstrap']
-
-try:
-    import pkg_resources
-    import setuptools
-    if not hasattr(pkg_resources, '_distribute'):
-        raise ImportError
-except ImportError:
-    ez = {}
-    if USE_DISTRIBUTE:
-        exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py'
-                         ).read() in ez
-        ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True)
-    else:
-        exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
-                             ).read() in ez
-        ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
-
-    reload(sys.modules['pkg_resources'])
-    import pkg_resources
-
-if sys.platform == 'win32':
-    def quote(c):
-        if ' ' in c:
-            return '"%s"' % c # work around spawn lamosity on windows
-        else:
-            return c
-else:
-    def quote (c):
-        return c
-
-cmd = 'from setuptools.command.easy_install import main; main()'
-ws  = pkg_resources.working_set
-
-if USE_DISTRIBUTE:
-    requirement = 'distribute'
-else:
-    requirement = 'setuptools'
-
-if is_jython:
-    import subprocess
-
-    assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
-           quote(tmpeggs), 'zc.buildout' + VERSION],
-           env=dict(os.environ,
-               PYTHONPATH=
-               ws.find(pkg_resources.Requirement.parse(requirement)).location
-               ),
-           ).wait() == 0
-
-else:
-    assert os.spawnle(
-        os.P_WAIT, sys.executable, quote (sys.executable),
-        '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout' + VERSION,
-        dict(os.environ,
-            PYTHONPATH=
-            ws.find(pkg_resources.Requirement.parse(requirement)).location
-            ),
-        ) == 0
-
-ws.add_entry(tmpeggs)
-ws.require('zc.buildout' + VERSION)
-import zc.buildout.buildout
-zc.buildout.buildout.main(args)
-shutil.rmtree(tmpeggs)

Copied: zc.buildout/trunk/bootstrap/bootstrap.py (from rev 115416, zc.buildout/trunk/bootstrap/newbootstrap.py)
===================================================================
--- zc.buildout/trunk/bootstrap/bootstrap.py	                        (rev 0)
+++ zc.buildout/trunk/bootstrap/bootstrap.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -0,0 +1,258 @@
+##############################################################################
+#
+# 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, subprocess
+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
+
+# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments.
+stdout, stderr = subprocess.Popen(
+    [sys.executable, '-Sc',
+     'try:\n'
+     '    import ConfigParser\n'
+     'except ImportError:\n'
+     '    print 1\n'
+     'else:\n'
+     '    print 0\n'],
+    stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+has_broken_dash_S = bool(int(stdout.strip()))
+
+# 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 not has_broken_dash_S and '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("-t", "--accept-buildout-test-releases",
+                  dest='accept_buildout_test_releases',
+                  action="store_true", default=False,
+                  help=("Normally, if you do not specify a --version, the "
+                        "bootstrap script and buildout gets the newest "
+                        "*final* versions of zc.buildout and its recipes and "
+                        "extensions for you.  If you use this flag, "
+                        "bootstrap and buildout will get the newest releases "
+                        "even if they are alphas or betas."))
+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
+
+if options.accept_buildout_test_releases:
+    args.append('buildout:accept-buildout-test-releases=true')
+args.append('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 not has_broken_dash_S:
+    cmd.insert(1, '-S')
+
+find_links = options.download_base
+if not find_links:
+    find_links = os.environ.get('bootstrap-testing-find-links')
+if find_links:
+    cmd.extend(['-f', quote(find_links)])
+
+if options.use_distribute:
+    setup_requirement = 'distribute'
+else:
+    setup_requirement = 'setuptools'
+ws = pkg_resources.working_set
+setup_requirement_path = ws.find(
+    pkg_resources.Requirement.parse(setup_requirement)).location
+env = dict(
+    os.environ,
+    PYTHONPATH=setup_requirement_path)
+
+requirement = 'zc.buildout'
+version = options.version
+if version is None and not options.accept_buildout_test_releases:
+    # Figure out the most recent final version of zc.buildout.
+    import setuptools.package_index
+    _final_parts = '*final-', '*final'
+    def _final_version(parsed_version):
+        for part in parsed_version:
+            if (part[:1] == '*') and (part not in _final_parts):
+                return False
+        return True
+    index = setuptools.package_index.PackageIndex(
+        search_path=[setup_requirement_path])
+    if find_links:
+        index.add_find_links((find_links,))
+    req = pkg_resources.Requirement.parse(requirement)
+    if index.obtain(req) is not None:
+        best = []
+        bestv = None
+        for dist in index[req.project_name]:
+            distv = dist.parsed_version
+            if _final_version(distv):
+                if bestv is None or distv > bestv:
+                    best = [dist]
+                    bestv = distv
+                elif distv == bestv:
+                    best.append(dist)
+        if best:
+            best.sort()
+            version = best[-1].version
+if version:
+    requirement = '=='.join((requirement, version))
+cmd.append(requirement)
+
+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)

Deleted: zc.buildout/trunk/bootstrap/newbootstrap.py
===================================================================
--- zc.buildout/trunk/bootstrap/newbootstrap.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/bootstrap/newbootstrap.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -1,200 +0,0 @@
-##############################################################################
-#
-# 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)

Modified: zc.buildout/trunk/buildout.cfg
===================================================================
--- zc.buildout/trunk/buildout.cfg	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/buildout.cfg	2010-08-23 15:04:24 UTC (rev 115887)
@@ -11,16 +11,15 @@
 [test]
 recipe = zc.recipe.testrunner
 eggs =
-  zc.buildout
+  zc.buildout[test]
   zc.recipe.egg
   z3c.recipe.scripts
-  zope.testing
 
 # Tests that can be run wo a network
 [oltest]
 recipe = zc.recipe.testrunner
 eggs =
-  zc.buildout
+  zc.buildout[test]
   zc.recipe.egg
   z3c.recipe.scripts
 defaults =

Modified: zc.buildout/trunk/dev.py
===================================================================
--- zc.buildout/trunk/dev.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/dev.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -19,7 +19,7 @@
 $Id$
 """
 
-import os, shutil, sys, subprocess, urllib2
+import os, shutil, sys, subprocess, urllib2, subprocess
 from optparse import OptionParser
 
 if sys.platform == 'win32':
@@ -31,11 +31,15 @@
 else:
     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
 # 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:
+if not has_broken_dash_S and 'site' in sys.modules:
     # We will restart with python -S.
     args = sys.argv[:]
     args[0:0] = [sys.executable, '-S']
@@ -117,11 +121,15 @@
 
 env = os.environ.copy() # Windows needs yet-to-be-determined values from this.
 env['PYTHONPATH'] = os.path.dirname(pkg_resources.__file__)
-subprocess.Popen(
-    [sys.executable] +
-    ['setup.py', '-q', 'develop', '-m', '-x', '-d', 'develop-eggs'],
-    env=env).wait()
 
+cmd = [sys.executable,
+       'setup.py', '-q', 'develop', '-m', '-x', '-d', 'develop-eggs']
+
+if not has_broken_dash_S:
+    cmd.insert(1, '-S')
+
+subprocess.Popen(cmd, env=env).wait()
+
 pkg_resources.working_set.add_entry('src')
 
 import zc.buildout.easy_install

Modified: zc.buildout/trunk/setup.py
===================================================================
--- zc.buildout/trunk/setup.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/setup.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -12,7 +12,7 @@
 #
 ##############################################################################
 name = "zc.buildout"
-version = "1.5.0dev"
+version = "1.5.0"
 
 import os
 from setuptools import setup
@@ -23,6 +23,8 @@
 long_description=(
         read('README.txt')
         + '\n' +
+        read('SYSTEM_PYTHON_HELP.txt')
+        + '\n' +
         'Detailed Documentation\n'
         '**********************\n'
         + '\n' +
@@ -83,6 +85,7 @@
     install_requires = 'setuptools',
     include_package_data = True,
     entry_points = entry_points,
+    extras_require = dict(test=['zope.testing']),
     zip_safe=False,
     classifiers = [
        'Intended Audience :: Developers',

Modified: zc.buildout/trunk/src/zc/buildout/allowhosts.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/allowhosts.txt	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/allowhosts.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -2,14 +2,14 @@
 -----------
 
 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
 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.
 
-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`
 (see `easy_install allow-hosts option`_).
 
@@ -17,7 +17,7 @@
 
     [buildout]
     ...
-    
+
     allow-hosts =
         *.python.org
         example.com
@@ -36,7 +36,7 @@
     ...     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
 local files::
 
@@ -55,14 +55,11 @@
 
 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'
-    Installing eggs.
-    <BLANKLINE>
+    ...
     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:
       Installing eggs.
       Getting distribution for 'kss.core'.
@@ -91,14 +88,11 @@
 
 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'
-    Installing eggs.
-    <BLANKLINE>
+    ...
     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:
       Installing eggs.
       Getting distribution for 'kss.core'.
@@ -115,7 +109,7 @@
     ... [buildout]
     ... parts=python
     ... foo = ${python:interpreter}
-    ... 
+    ...
     ... [python]
     ... recipe=zc.recipe.egg
     ... eggs=zc.buildout

Modified: zc.buildout/trunk/src/zc/buildout/bootstrap.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/bootstrap.txt	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/bootstrap.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -47,16 +47,116 @@
     X...
     d  zc.buildout-...egg
 
+The buildout script it has generated is a new-style script, using a
+customized site.py.
+
+    >>> buildout_script = join(sample_buildout, 'bin', 'buildout')
+    >>> if sys.platform.startswith('win'):
+    ...     buildout_script += '-script.py'
+    >>> print open(buildout_script).read() # doctest: +ELLIPSIS
+    #...
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+        '/sample/parts/buildout',
+        ]
+    <BLANKLINE>
+    <BLANKLINE>
+    import os
+    path = sys.path[0]
+    if os.environ.get('PYTHONPATH'):
+        path = os.pathsep.join([path, os.environ['PYTHONPATH']])
+    os.environ['PYTHONPATH'] = path
+    import site # imports custom buildout-generated site.py
+    <BLANKLINE>
+    import zc.buildout.buildout
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.buildout.buildout.main()
+    <BLANKLINE>
+
+The bootstrap process prefers final versions of zc.buildout, so it has
+selected the (generated-locally) 99.99 egg rather than the also-available
+100.0b1 egg.  We can see that in the buildout script's site.py.
+
+    >>> buildout_site_py = join(
+    ...     sample_buildout, 'parts', 'buildout', 'site.py')
+    >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS
+    "...
+        buildout_paths = [
+            '/sample/eggs/setuptools-...egg',
+            '/sample/eggs/zc.buildout-99.99-pyN.N.egg'
+            ]
+    ...
+
+If you want to accept early releases of zc.buildout, you either need to
+specify an explicit version (using --version here and specifying the
+version in the buildout configuration file using the
+``buildout-version`` option or the ``versions`` option) or specify that you
+accept early releases by using ``--accept-buildout-test-releases`` on the
+bootstrap script.
+
+Here's an example.
+
+    >>> ignored = system(
+    ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
+    ...     'bootstrap.py --accept-buildout-test-releases')
+    >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS
+    "...
+        buildout_paths = [
+            '/sample/eggs/setuptools-...egg',
+            '/sample/eggs/zc.buildout-100.0b1-pyN.N.egg'
+            ]
+    ...
+
+Notice we are now using zc.buildout 100.0b1, a non-final release.
+
+The buildout script remembers the decision to accept early releases, and
+alerts the user.
+
+    >>> print system(join('bin', 'buildout')),
+    ... # doctest: +NORMALIZE_WHITESPACE
+    NOTE: Accepting early releases of build system packages.  Rerun bootstrap
+          without --accept-buildout-test-releases (-t) to return to default
+          behavior.
+
+This is accomplished within the script itself.
+
+    >>> 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.')
+    ...
+
+As the note says, to undo, you just need to re-run bootstrap without
+--accept-buildout-test-releases.
+
+    >>> ignored = system(
+    ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
+    ...     'bootstrap.py')
+    >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS
+    "...
+        buildout_paths = [
+            '/sample/eggs/setuptools-...egg',
+            '/sample/eggs/zc.buildout-99.99-pyN.N.egg'
+            ]
+    ...
+    >>> ('buildout:accept-buildout-test-releases=true' in
+    ... open(buildout_script).read())
+    False
+
 Now we will try the `--version` option, which lets you define a version for
 `zc.buildout`. If not provided, bootstrap will look for the latest one.
 
 Let's try with an unknown version::
 
-    >>> print 'X'; print system(
+    >>> print 'XX'; print system(
     ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
     ...     'bootstrap.py --version UNKNOWN'); print 'X' # doctest: +ELLIPSIS
     ...
-    X
+    X...
     No local packages or download links found for zc.buildout==UNKNOWN...
     ...
 
@@ -71,11 +171,9 @@
     <BLANKLINE>
     X
 
-Let's make sure the generated `buildout` script uses it::
+Versions older than 1.5.0 put their egg dependencies in the ``buildout`` script.
+Let's make sure it was generated as we expect::
 
-    >>> buildout_script = join(sample_buildout, 'bin', 'buildout')
-    >>> if sys.platform.startswith('win'):
-    ...     buildout_script += '-script.py'
     >>> print open(buildout_script).read() # doctest: +ELLIPSIS
     #...
     <BLANKLINE>
@@ -102,7 +200,7 @@
     <BLANKLINE>
     X
 
-Let's make sure the generated `buildout` script uses it::
+Let's make sure the generated ``buildout`` script uses it::
 
     >>> print open(buildout_script).read() # doctest: +ELLIPSIS
     #...
@@ -119,7 +217,7 @@
         zc.buildout.buildout.main()
     <BLANKLINE>
 
-`zc.buildout` now can also run with `Distribute` with the `--distribute`
+``zc.buildout`` now can also run with `Distribute` with the `--distribute`
 option::
 
     >>> print 'X'; print system(
@@ -128,27 +226,18 @@
     ...
     X
     ...
-    Generated script '/sample/bin/buildout'.
-    <BLANKLINE>
+    Generated script '/sample/bin/buildout'...
     X
 
-Let's make sure the generated `buildout` script uses it::
+Let's make sure the generated ``site.py`` uses it::
+    >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS
+    "...
+        buildout_paths = [
+            '/sample/eggs/distribute-...egg',
+            '/sample/eggs/zc.buildout-99.99-pyN.N.egg'
+            ]
+    ...
 
-    >>> 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(
@@ -158,12 +247,11 @@
     ...
     X
     ...
-    Generated script '/sample/bin/buildout'.
-    <BLANKLINE>
+    Generated script '/sample/bin/buildout'...
     X
 
-Let's make sure the generated `buildout` script uses ``Distribute`` *and*
-``zc.buildout-1.2.1``::
+Let's make sure the old-style generated ``buildout`` script uses
+``Distribute`` *and* ``zc.buildout-1.2.1``::
 
     >>> print open(buildout_script).read() # doctest: +ELLIPSIS
     #...
@@ -192,22 +280,80 @@
     ...
     X
     ...
-    Generated script '/sample/bin/buildout'.
-    <BLANKLINE>
+    Generated script '/sample/bin/buildout'...
     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):
+    ...     import sys, pprint
+    ...     pprint.pprint(kwargs, width=40)
+    ...     sys.exit()
+    ... ''')
+    >>> print system(
+    ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
+    ...     'bootstrap.py --setup-source=./ez_setup.py')
+    ... # doctest: +ELLIPSIS
+    {'download_delay': 0,
+     'to_dir': '...'}
+    <BLANKLINE>
+
+You can also pass a download-cache, and a place in which eggs should be stored
+(they are normally stored in a temporary directory).
+
+    >>> print system(
+    ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
+    ...     'bootstrap.py --setup-source=./ez_setup.py '+
+    ...     '--download-base=./download-cache --eggs=eggs')
+    ... # doctest: +ELLIPSIS
+    {'download_base': '/sample/download-cache/',
+     'download_delay': 0,
+     'to_dir': '/sample/eggs'}
+    <BLANKLINE>
+
 Here's the entire help text.
 
     >>> print system(
     ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
     ...     'bootstrap.py --help'),
     ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
-    Usage: bootstrap.py [options]
+    Usage: [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
     <BLANKLINE>
+    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>
+    <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.
+      -t, --accept-buildout-test-releases
+                            Normally, if you do not specify a --version, the
+                            bootstrap script and buildout gets the newest *final*
+                            versions of zc.buildout and its recipes and extensions
+                            for you.  If you use this flag, bootstrap and buildout
+                            will get the newest releases even if they are alphas
+                            or betas.
       -c CONFIG_FILE        Specify the path to the buildout configuration file to
                             be used.

Modified: zc.buildout/trunk/src/zc/buildout/buildout.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/buildout.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/buildout.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -34,6 +34,7 @@
 import sys
 import tempfile
 import UserDict
+import warnings
 import zc.buildout
 import zc.buildout.download
 import zc.buildout.easy_install
@@ -51,6 +52,9 @@
 if is_jython:
     import subprocess
 
+_sys_executable_has_broken_dash_S = (
+    zc.buildout.easy_install._has_broken_dash_S(sys.executable))
+
 class MissingOption(zc.buildout.UserError, KeyError):
     """A required option was missing.
     """
@@ -112,6 +116,7 @@
     return data
 
 _buildout_default_options = _annotate_section({
+    'accept-buildout-test-releases': 'false',
     'allow-hosts': '*',
     'allow-picked-versions': 'true',
     'bin-directory': 'bin',
@@ -230,6 +235,8 @@
         self._logger = logging.getLogger('zc.buildout')
         self.offline = (buildout_section['offline'] == 'true')
         self.newest = (buildout_section['newest'] == 'true')
+        self.accept_buildout_test_releases = (
+            buildout_section['accept-buildout-test-releases'] == 'true')
 
         ##################################################################
         ## WARNING!!!
@@ -263,42 +270,26 @@
 
         self._setup_logging()
 
-        offline = options['offline']
-        if offline not in ('true', 'false'):
-            self._error('Invalid value for offline option: %s', offline)
-        self.offline = (offline == 'true')
-
-        if self.offline:
-            newest = options['newest'] = 'false'
-        else:
-            newest = options['newest']
-            if newest not in ('true', 'false'):
-                self._error('Invalid value for newest option: %s', newest)
-        self.newest = (newest == 'true')
-
         versions = options.get('versions')
         if versions:
             zc.buildout.easy_install.default_versions(dict(self[versions]))
 
-        prefer_final = options['prefer-final']
-        if prefer_final not in ('true', 'false'):
-            self._error('Invalid value for prefer-final option: %s',
-                        prefer_final)
-        zc.buildout.easy_install.prefer_final(prefer_final=='true')
 
-        use_dependency_links = options['use-dependency-links']
-        if use_dependency_links not in ('true', 'false'):
-            self._error('Invalid value for use-dependency-links option: %s',
-                        use_dependency_links)
+        self.offline = options.get_bool('offline')
+        if self.offline:
+            options['newest'] = 'false'
+        self.newest = options.get_bool('newest')
+        zc.buildout.easy_install.prefer_final(
+            options.get_bool('prefer-final'))
+        self.accept_buildout_test_releases = options.get_bool(
+            'accept-buildout-test-releases')
         zc.buildout.easy_install.use_dependency_links(
-            use_dependency_links == 'true')
-
-        allow_picked_versions = options['allow-picked-versions']
-        if allow_picked_versions not in ('true', 'false'):
-            self._error('Invalid value for allow-picked-versions option: %s',
-                        allow_picked_versions)
+            options.get_bool('use-dependency-links'))
         zc.buildout.easy_install.allow_picked_versions(
-            allow_picked_versions == 'true')
+            options.get_bool('allow-picked-versions'))
+        zc.buildout.easy_install.install_from_cache(
+            options.get_bool('install-from-cache'))
+        zc.buildout.easy_install.always_unzip(options.get_bool('unzip'))
 
         download_cache = options.get('download-cache')
         if download_cache:
@@ -315,19 +306,6 @@
 
             zc.buildout.easy_install.download_cache(download_cache)
 
-        install_from_cache = options['install-from-cache']
-        if install_from_cache not in ('true', 'false'):
-            self._error('Invalid value for install-from-cache option: %s',
-                        install_from_cache)
-        zc.buildout.easy_install.install_from_cache(
-            install_from_cache=='true')
-
-        always_unzip = options['unzip']
-        if always_unzip not in ('true', 'false'):
-            self._error('Invalid value for unzip option: %s',
-                        always_unzip)
-        zc.buildout.easy_install.always_unzip(always_unzip=='true')
-
         # "Use" each of the defaults so they aren't reported as unused options.
         for name in _buildout_default_options:
             options[name]
@@ -359,7 +337,8 @@
                 distributions, options['executable'],
                 [options['develop-eggs-directory'],
                  options['eggs-directory']],
-                include_site_packages=False,
+                include_site_packages=_sys_executable_has_broken_dash_S,
+                prefer_final=not self.accept_buildout_test_releases,
                 )
         else:
             ws = zc.buildout.easy_install.install(
@@ -370,7 +349,8 @@
                 path=[options['develop-eggs-directory']],
                 newest=self.newest,
                 allow_hosts=self._allow_hosts,
-                include_site_packages=False,
+                include_site_packages=_sys_executable_has_broken_dash_S,
+                prefer_final=not self.accept_buildout_test_releases,
                 )
 
         # Now copy buildout and setuptools eggs, and record destination eggs:
@@ -393,7 +373,9 @@
                     else:
                         shutil.copy2(dist.location, dest)
 
-        # Create buildout script
+        # Create buildout script.
+        # Ideally the (possibly) new version of buildout would get a
+        # chance to write the script.  Not sure how to do that.
         ws = pkg_resources.WorkingSet(entries)
         ws.require('zc.buildout')
         partsdir = os.path.join(options['parts-directory'], 'buildout')
@@ -406,9 +388,19 @@
         else:
             assert relative_paths == 'false'
             relative_paths = ''
+        if (self.accept_buildout_test_releases and
+            self._annotated['buildout']['accept-buildout-test-releases'][1] ==
+            'COMMAND_LINE_VALUE'):
+            # Bootstrap was called with '--accept-buildout-test-releases'.
+            # Continue to honor that setting.
+            script_initialization = _early_release_initialization_code
+        else:
+            script_initialization = ''
         zc.buildout.easy_install.sitepackage_safe_scripts(
             options['bin-directory'], ws, options['executable'], partsdir,
-            reqs=['zc.buildout'], relative_paths=relative_paths)
+            reqs=['zc.buildout'], relative_paths=relative_paths,
+            include_site_packages=_sys_executable_has_broken_dash_S,
+            script_initialization=script_initialization,)
 
     init = bootstrap
 
@@ -422,7 +414,7 @@
         # for eggs:
         sys.path.insert(0, self['buildout']['develop-eggs-directory'])
 
-        # Check for updates. This could cause the process to be rstarted
+        # Check for updates. This could cause the process to be restarted.
         self._maybe_upgrade()
 
         # load installed data
@@ -475,7 +467,7 @@
         # compute new part recipe signatures
         self._compute_part_signatures(install_parts)
 
-        # uninstall parts that are no-longer used or who's configs
+        # uninstall parts that are no-longer used or whose configs
         # have changed
         for part in reversed(installed_parts):
             if part in install_parts:
@@ -621,11 +613,11 @@
         f.close()
 
     def _uninstall_part(self, part, installed_part_options):
-        # ununstall part
+        # uninstall part
         __doing__ = 'Uninstalling %s.', part
         self._logger.info(*__doing__)
 
-        # run uinstall recipe
+        # run uninstall recipe
         recipe, entry = _recipe(installed_part_options[part])
         try:
             uninstaller = _install_and_load(
@@ -854,7 +846,8 @@
             index = options.get('index'),
             path = [options['develop-eggs-directory']],
             allow_hosts = self._allow_hosts,
-            include_site_packages=False
+            include_site_packages=_sys_executable_has_broken_dash_S,
+            prefer_final=not self.accept_buildout_test_releases,
             )
 
         upgraded = []
@@ -902,15 +895,27 @@
 
         # the new dist is different, so we've upgraded.
         # Update the scripts and return True
+        # Ideally the new version of buildout would get a chance to write the
+        # script.  Not sure how to do that.
         partsdir = os.path.join(options['parts-directory'], 'buildout')
         if os.path.exists(partsdir):
             # This is primarily for unit tests, in which .py files change too
             # fast for Python to know to regenerate the .pyc/.pyo files.
             shutil.rmtree(partsdir)
         os.mkdir(partsdir)
+        if (self.accept_buildout_test_releases and
+            self._annotated['buildout']['accept-buildout-test-releases'][1] ==
+            'COMMAND_LINE_VALUE'):
+            # Bootstrap was called with '--accept-buildout-test-releases'.
+            # Continue to honor that setting.
+            script_initialization = _early_release_initialization_code
+        else:
+            script_initialization = ''
         zc.buildout.easy_install.sitepackage_safe_scripts(
             options['bin-directory'], ws, sys.executable, partsdir,
-            reqs=['zc.buildout'])
+            reqs=['zc.buildout'],
+            include_site_packages=_sys_executable_has_broken_dash_S,
+            script_initialization=script_initialization)
 
         # Restart
         args = map(zc.buildout.easy_install._safe_arg, sys.argv)
@@ -951,7 +956,8 @@
                 links = self['buildout'].get('find-links', '').split(),
                 index = self['buildout'].get('index'),
                 newest=self.newest, allow_hosts=self._allow_hosts,
-                include_site_packages=False)
+                include_site_packages=_sys_executable_has_broken_dash_S,
+                prefer_final=not self.accept_buildout_test_releases)
 
             # Clear cache because extensions might now let us read pages we
             # couldn't read before.
@@ -982,6 +988,7 @@
         setup = os.path.abspath(setup)
 
         fd, tsetup = tempfile.mkstemp()
+        exe = zc.buildout.easy_install._safe_arg(sys.executable)
         try:
             os.write(fd, zc.buildout.easy_install.runsetup_template % dict(
                 setuptools=pkg_resources_loc,
@@ -995,14 +1002,10 @@
                 for a in args:
                     arg_list.append(zc.buildout.easy_install._safe_arg(a))
 
-                subprocess.Popen(
-                    [zc.buildout.easy_install._safe_arg(sys.executable)]
-                    + list(tsetup)
-                    + arg_list
-                    ).wait()
+                subprocess.Popen([exe] + list(tsetup) + arg_list).wait()
 
             else:
-                os.spawnl(os.P_WAIT, sys.executable, zc.buildout.easy_install._safe_arg (sys.executable), tsetup,
+                os.spawnl(os.P_WAIT, sys.executable, exe, tsetup,
                         *[zc.buildout.easy_install._safe_arg(a)
                             for a in args])
         finally:
@@ -1069,8 +1072,8 @@
                 working_set=pkg_resources.working_set,
                 newest=buildout.newest,
                 allow_hosts=buildout._allow_hosts,
-                include_site_packages=False,
-                )
+                include_site_packages=_sys_executable_has_broken_dash_S,
+                prefer_final=not buildout.accept_buildout_test_releases)
 
         __doing__ = 'Loading %s recipe entry %s:%s.', group, spec, entry
         return pkg_resources.load_entry_point(
@@ -1083,6 +1086,7 @@
             group, entry, spec, v)
         raise
 
+
 class Options(UserDict.DictMixin):
 
     def __init__(self, buildout, section, data):
@@ -1292,6 +1296,32 @@
                 self.name)
         return self._created
 
+    def query_bool(self, name, default=None):
+        """Given a name, return a boolean value for that name.
+
+        ``default``, if given, should be 'true', 'false', or None.
+        """
+        if default is not None:
+            value = self.setdefault(name, default=default)
+        else:
+            value = self.get(name)
+            if value is None:
+                return value
+        return _convert_bool(name, value)
+
+    def get_bool(self, name):
+        """Given a name, return a boolean value for that name.
+        """
+        return _convert_bool(name, self[name])
+
+
+def _convert_bool(name, value):
+    if value not in ('true', 'false'):
+        raise zc.buildout.UserError(
+            'Invalid value for %s option: %s' % (name, value))
+    else:
+        return value == 'true'
+
 _spacey_nl = re.compile('[ \t\r\f\v]*\n[ \t\r\f\v\n]*'
                         '|'
                         '^[ \t\r\f\v]+'
@@ -1514,6 +1544,13 @@
                               % (section, ' '.join(map(repr, unused)))
                               )
 
+_early_release_initialization_code = """\
+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.')
+"""
+
 _usage = """\
 Usage: buildout [options] [assignments] [command [command arguments]]
 
@@ -1577,6 +1614,11 @@
     will be started. This is especially useful for debuging recipe
     problems.
 
+  -s
+
+    Squelch warnings about using an executable with a broken -S
+    implementation.
+
 Assignments are of the form: section:option=value and are used to
 provide configuration options that override those given in the
 configuration file.  For example, to run the buildout in offline mode,
@@ -1642,11 +1684,12 @@
     windows_restart = False
     user_defaults = True
     debug = False
+    ignore_broken_dash_s = False
     while args:
         if args[0][0] == '-':
             op = orig_op = args.pop(0)
             op = op[1:]
-            while op and op[0] in 'vqhWUoOnNDA':
+            while op and op[0] in 'vqhWUoOnNDAs':
                 if op[0] == 'v':
                     verbosity += 10
                 elif op[0] == 'q':
@@ -1665,6 +1708,8 @@
                     options.append(('buildout', 'newest', 'false'))
                 elif op[0] == 'D':
                     debug = True
+                elif op[0] == 's':
+                    ignore_broken_dash_s = True
                 else:
                     _help()
                 op = op[1:]
@@ -1708,6 +1753,17 @@
             # The rest should be commands, so we'll stop here
             break
 
+    if verbosity < 0 or ignore_broken_dash_s:
+        broken_dash_S_filter_action = 'ignore'
+    elif verbosity == 0: # This is the default.
+        broken_dash_S_filter_action = 'once'
+    else:
+        broken_dash_S_filter_action = 'default'
+    warnings.filterwarnings(
+        broken_dash_S_filter_action,
+        re.escape(
+            zc.buildout.easy_install.BROKEN_DASH_S_WARNING),
+        UserWarning)
     if verbosity:
         options.append(('buildout', 'verbosity', str(verbosity)))
 

Modified: zc.buildout/trunk/src/zc/buildout/buildout.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/buildout.txt	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/buildout.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -729,6 +729,8 @@
     ==================
     <BLANKLINE>
     [buildout]
+    accept-buildout-test-releases= false
+        DEFAULT_VALUE
     allow-hosts= *
         DEFAULT_VALUE
     allow-picked-versions= true
@@ -2227,6 +2229,7 @@
     <BLANKLINE>
     Configuration data:
     [buildout]
+    accept-buildout-test-releases = false
     allow-hosts = *
     allow-picked-versions = true
     bin-directory = /sample-buildout/bin
@@ -2484,26 +2487,34 @@
 Preferring Final Releases
 -------------------------
 
-Currently, when searching for new releases, the newest available
-release is used.  This isn't usually ideal, as you may get a
-development release or alpha releases not ready to be widely used.
-You can request that final releases be preferred using the prefer
-final option in the buildout section::
+Currently, when searching for new releases of your project's
+dependencies, the newest available release is used.  This isn't usually
+ideal, as you may get a development release or alpha releases not ready
+to be widely used. You can request that final releases be preferred
+using the ``prefer-final`` option in the buildout section::
 
   [buildout]
   ...
   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
 releases that satisfy distribution requirements, then those releases
-are used even if newer non-final releases are available.  The buildout
-prefer-final option can be used to override this behavior.
+are used even if newer non-final releases are available.
 
-In buildout version 2, final releases will be preferred by default.
-You will then need to use a false value for prefer-final to get the
-newest releases.
+In buildout version 2, all final releases will be preferred by
+default--that is ``prefer-final`` will also default to 'true'. You will
+then need to use a 'false' value for ``prefer-final`` to get the newest
+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
 ---------------------
 

Modified: zc.buildout/trunk/src/zc/buildout/debugging.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/debugging.txt	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/debugging.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -5,12 +5,12 @@
 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
 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:
 
     >>> mkdir(sample_buildout, 'recipes')
 
-    >>> write(sample_buildout, 'recipes', 'mkdir.py', 
+    >>> write(sample_buildout, 'recipes', 'mkdir.py',
     ... """
     ... import os, zc.buildout
     ...
@@ -35,7 +35,7 @@
     >>> write(sample_buildout, 'recipes', 'setup.py',
     ... """
     ... from setuptools import setup
-    ... 
+    ...
     ... setup(name = "recipes",
     ...       entry_points = {'zc.buildout': ['mkdir = mkdir:Mkdir']},
     ...       )

Modified: zc.buildout/trunk/src/zc/buildout/dependencylinks.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/dependencylinks.txt	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/dependencylinks.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -20,7 +20,7 @@
 
 Turn on logging on this server so that we can see when eggs are pulled
 from it.
-    
+
     >>> get(link_server2 + 'enable_server_logging')
     GET 200 /enable_server_logging
     ''
@@ -83,10 +83,9 @@
     ...     for egg in glob(join(sample_buildout, 'eggs', 'demoneeded*.egg')):
     ...         remove(sample_buildout, 'eggs', egg)
     >>> remove_demoneeded_egg()
-    >>> print system(buildout)
+    >>> print system(buildout) # doctest: +ELLIPSIS
     Develop: '/sample-buildout/depdemo'
-    Updating eggs.
-    Couldn't find index page for 'demoneeded' (maybe misspelled?)
+    ...
     Getting distribution for 'demoneeded'.
     While:
       Updating eggs.

Modified: zc.buildout/trunk/src/zc/buildout/easy_install.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/easy_install.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/easy_install.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -33,6 +33,7 @@
 import subprocess
 import sys
 import tempfile
+import warnings
 import zc.buildout
 import zipimport
 
@@ -54,11 +55,22 @@
 is_distribute = (
     pkg_resources.Requirement.parse('setuptools').key=='distribute')
 
+BROKEN_DASH_S_WARNING = (
+    '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).')
+
 if is_jython:
     import java.lang.System
     jython_os_name = (java.lang.System.getProperties()['os.name']).lower()
 
-
 setuptools_loc = pkg_resources.working_set.find(
     pkg_resources.Requirement.parse('setuptools')
     ).location
@@ -71,6 +83,25 @@
 if os.path.normpath(setuptools_loc) != os.path.normpath(buildout_loc):
     buildout_and_setuptools_path.append(buildout_loc)
 
+def _has_broken_dash_S(executable):
+    """Detect https://bugs.launchpad.net/virtualenv/+bug/572545 ."""
+    # The first attempt here was to simply have the executable attempt to import
+    # ConfigParser and return the return code. That worked except for tests on
+    # Windows, where the return code was wrong for the fake Python executable
+    # generated by the virtualenv.txt test, apparently because setuptools' .exe
+    # file does not pass the -script.py's returncode back properly, at least in
+    # some circumstances. Therefore...print statements.
+    stdout, stderr = subprocess.Popen(
+        [executable, '-Sc',
+         'try:\n'
+         '    import ConfigParser\n'
+         'except ImportError:\n'
+         '    print 1\n'
+         'else:\n'
+         '    print 0\n'],
+        stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+    return bool(int(stdout.strip()))
+
 def _get_system_paths(executable):
     """Return lists of standard lib and site paths for executable.
     """
@@ -124,7 +155,8 @@
     return (stdlib, site_paths)
 
 def _get_version_info(executable):
-    cmd = [executable, '-Sc', 'import sys; print repr(sys.version_info)']
+    cmd = [executable, '-Sc',
+           'import sys; print(repr(tuple(x for x in sys.version_info)))']
     _proc = subprocess.Popen(
         cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     stdout, stderr = _proc.communicate();
@@ -210,10 +242,10 @@
     _safe_arg = str
 
 # The following string is used to run easy_install in
-# Installer._call_easy_install.  It is started with python -S (that is,
-# don't import site at start).  That flag, and all of the code in this
-# snippet above the last two lines, exist to work around a relatively rare
-# problem.  If
+# Installer._call_easy_install.  It is usually started with python -S
+# (that is, don't import site at start).  That flag, and all of the code
+# in this snippet above the last two lines, exist to work around a
+# relatively rare problem.  If
 #
 # - your buildout configuration is trying to install a package that is within
 #   a namespace package, and
@@ -239,7 +271,7 @@
 # for another description of the problem).  Simply starting Python with
 # -S addresses the problem in Python 2.4 and 2.5, but Python 2.6's
 # distutils imports a value from the site module, so we unfortunately
-# have to do more drastic surgery in the _easy_install_cmd code below.
+# have to do more drastic surgery in the _easy_install_preface code below.
 #
 # Here's an example of the .pth files created by setuptools when using that
 # flag:
@@ -265,17 +297,16 @@
 # unnecessary for site.py to preprocess these packages, so it should be
 # fine, as far as can be guessed as of this writing.)  Finally, it
 # imports easy_install and runs it.
-
-_easy_install_cmd = _safe_arg('''\
+_easy_install_preface = '''\
 import sys,os;\
 p = sys.path[:];\
 import site;\
 sys.path[:] = p;\
 [sys.modules.pop(k) 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'))];\
-from setuptools.command.easy_install import main;\
-main()''')
+ not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))];'''
+_easy_install_cmd = (
+    'from setuptools.command.easy_install import main;main()')
 
 
 class Installer:
@@ -302,7 +333,8 @@
                  use_dependency_links=None,
                  allow_hosts=('*',),
                  include_site_packages=None,
-                 allowed_eggs_from_site_packages=None
+                 allowed_eggs_from_site_packages=None,
+                 prefer_final=None,
                  ):
         self._dest = dest
         self._allow_hosts = allow_hosts
@@ -316,12 +348,15 @@
 
         if use_dependency_links is not None:
             self._use_dependency_links = use_dependency_links
+        if prefer_final is not None:
+            self._prefer_final = prefer_final
         self._links = links = list(_fix_file_links(links))
         if self._download_cache and (self._download_cache not in links):
             links.insert(0, self._download_cache)
 
         self._index_url = index
         self._executable = executable
+        self._has_broken_dash_S = _has_broken_dash_S(self._executable)
         if always_unzip is not None:
             self._always_unzip = always_unzip
         path = (path and path[:] or [])
@@ -330,6 +365,17 @@
         if allowed_eggs_from_site_packages is not None:
             self._allowed_eggs_from_site_packages = tuple(
                 allowed_eggs_from_site_packages)
+        if self._has_broken_dash_S:
+            if (not self._include_site_packages or
+                self._allowed_eggs_from_site_packages != ('*',)):
+                # We can't do this if the executable has a broken -S.
+                warnings.warn(BROKEN_DASH_S_WARNING)
+                self._include_site_packages = True
+                self._allowed_eggs_from_site_packages = ('*',)
+            self._easy_install_cmd = _easy_install_cmd
+        else:
+            self._easy_install_cmd = _easy_install_preface + _easy_install_cmd
+        self._easy_install_cmd = _safe_arg(self._easy_install_cmd)
         stdlib, self._site_packages = _get_system_paths(executable)
         version_info = _get_version_info(executable)
         if version_info == sys.version_info:
@@ -488,7 +534,9 @@
         try:
             path = setuptools_loc
 
-            args = ('-Sc', _easy_install_cmd, '-mUNxd', _safe_arg(tmp))
+            args = ('-c', self._easy_install_cmd, '-mUNxd', _safe_arg(tmp))
+            if not self._has_broken_dash_S:
+                args = ('-S',) + args
             if self._always_unzip:
                 args += ('-Z', )
             level = logger.getEffectiveLevel()
@@ -785,7 +833,7 @@
     def _maybe_add_setuptools(self, ws, dist):
         if dist.has_metadata('namespace_packages.txt'):
             for r in dist.requires():
-                if r.project_name == 'setuptools':
+                if r.project_name in ('setuptools', 'distribute'):
                     break
             else:
                 # We have a namespace package but no requirement for setuptools
@@ -873,7 +921,13 @@
                         dist = best[req.key] = env.best_match(req, ws)
                     except pkg_resources.VersionConflict, err:
                         raise VersionConflict(err, ws)
-                    if dist is None:
+                    if dist is None or (
+                        dist.location in self._site_packages and not
+                        self.allow_site_package_egg(dist.project_name)):
+                        # If we didn't find a distribution in the
+                        # environment, or what we found is from site
+                        # packages and not allowed to be there, try
+                        # again.
                         if destination:
                             logger.debug('Getting required %r', str(req))
                         else:
@@ -1020,13 +1074,14 @@
             executable=sys.executable, always_unzip=None,
             path=None, working_set=None, newest=True, versions=None,
             use_dependency_links=None, allow_hosts=('*',),
-            include_site_packages=None, allowed_eggs_from_site_packages=None):
-    installer = Installer(dest, links, index, executable, always_unzip, path,
-                          newest, versions, use_dependency_links,
-                          allow_hosts=allow_hosts,
-                          include_site_packages=include_site_packages,
-                          allowed_eggs_from_site_packages=
-                            allowed_eggs_from_site_packages)
+            include_site_packages=None, allowed_eggs_from_site_packages=None,
+            prefer_final=None):
+    installer = Installer(
+        dest, links, index, executable, always_unzip, path, newest,
+        versions, use_dependency_links, allow_hosts=allow_hosts,
+        include_site_packages=include_site_packages,
+        allowed_eggs_from_site_packages=allowed_eggs_from_site_packages,
+        prefer_final=prefer_final)
     return installer.install(specs, working_set)
 
 
@@ -1035,11 +1090,11 @@
           executable=sys.executable,
           path=None, newest=True, versions=None, allow_hosts=('*',),
           include_site_packages=None, allowed_eggs_from_site_packages=None):
-    installer = Installer(dest, links, index, executable, True, path, newest,
-                          versions, allow_hosts=allow_hosts,
-                          include_site_packages=include_site_packages,
-                          allowed_eggs_from_site_packages=
-                            allowed_eggs_from_site_packages)
+    installer = Installer(
+        dest, links, index, executable, True, path, newest, versions,
+        allow_hosts=allow_hosts,
+        include_site_packages=include_site_packages,
+        allowed_eggs_from_site_packages=allowed_eggs_from_site_packages)
     return installer.build(spec, build_ext)
 
 
@@ -1135,23 +1190,25 @@
         [f() for f in undo]
 
 def working_set(specs, executable, path, include_site_packages=None,
-                allowed_eggs_from_site_packages=None):
+                allowed_eggs_from_site_packages=None, prefer_final=None):
     return install(
         specs, None, executable=executable, path=path,
         include_site_packages=include_site_packages,
-        allowed_eggs_from_site_packages=allowed_eggs_from_site_packages)
+        allowed_eggs_from_site_packages=allowed_eggs_from_site_packages,
+        prefer_final=prefer_final)
 
 ############################################################################
 # Script generation functions
 
-def scripts(reqs, working_set, executable, dest,
-            scripts=None,
-            extra_paths=(),
-            arguments='',
-            interpreter=None,
-            initialization='',
-            relative_paths=False,
-            ):
+def scripts(
+    reqs, working_set, executable, dest,
+    scripts=None,
+    extra_paths=(),
+    arguments='',
+    interpreter=None,
+    initialization='',
+    relative_paths=False,
+    ):
     """Generate scripts and/or an interpreter.
 
     See sitepackage_safe_scripts for a version that can be used with a Python
@@ -1171,11 +1228,24 @@
             _pyscript(spath, sname, executable, rpsetup))
     return generated
 
+# We need to give an alternate name to the ``scripts`` function so that it
+# can be referenced within sitepackage_safe_scripts, which uses ``scripts``
+# as an argument name.
+_original_scripts_function = scripts
+
 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=''):
+    reqs=(),
+    scripts=None,
+    interpreter=None,
+    extra_paths=(),
+    initialization='',
+    include_site_packages=False,
+    exec_sitecustomize=False,
+    relative_paths=False,
+    script_arguments='',
+    script_initialization='',
+    ):
     """Generate scripts and/or an interpreter from a system Python.
 
     This accomplishes the same job as the ``scripts`` function, above,
@@ -1183,6 +1253,12 @@
     Python site packages, if desired, and  choosing to execute the Python's
     sitecustomize.
     """
+    if _has_broken_dash_S(executable):
+        if not include_site_packages:
+            warnings.warn(BROKEN_DASH_S_WARNING)
+        return _original_scripts_function(
+            reqs, working_set, executable, dest, scripts, extra_paths,
+            script_arguments, interpreter, initialization, relative_paths)
     generated = []
     generated.append(_generate_sitecustomize(
         site_py_dest, executable, initialization, exec_sitecustomize))
@@ -1491,7 +1567,7 @@
     cmd = [executable, "-Sc",
            "import imp; "
            "fp, path, desc = imp.find_module(%r); "
-           "fp.close; "
+           "fp.close(); "
            "print path" % (name,)]
     env = os.environ.copy()
     # We need to make sure that PYTHONPATH, which will often be set to
@@ -1548,15 +1624,15 @@
     """
     path = _get_path(working_set, extra_paths)
     site_path = os.path.join(dest, 'site.py')
-    egg_path_string, preamble = _relative_path_and_setup(
-        site_path, path, relative_paths, indent_level=2, omit_os_import=True)
-    if preamble:
-        preamble = '\n'.join(
-            [(line and '    %s' % (line,) or line)
-             for line in preamble.split('\n')])
-    original_path_setup = ''
+    original_path_setup = preamble = ''
     if include_site_packages:
         stdlib, site_paths = _get_system_paths(executable)
+        # We want to make sure that paths from site-packages, such as those
+        # allowed by allowed_eggs_from_site_packages, always come last, or
+        # else site-packages paths may include packages that mask the eggs we
+        # really want.
+        path = [p for p in path if p not in site_paths]
+        # Now we set up the code we need.
         original_path_setup = original_path_snippet % (
             _format_paths((repr(p) for p in site_paths), 2),)
         distribution = working_set.find(
@@ -1570,10 +1646,19 @@
                     relative_paths)
             else:
                 location = repr(distribution.location)
-            preamble += namespace_include_site_packages_setup % (location,)
+            preamble = namespace_include_site_packages_setup % (location,)
             original_path_setup = (
                 addsitedir_namespace_originalpackages_snippet +
                 original_path_setup)
+        else:
+            preamble = '\n    setuptools_path = None'
+    egg_path_string, relative_preamble = _relative_path_and_setup(
+        site_path, path, relative_paths, indent_level=2, omit_os_import=True)
+    if relative_preamble:
+        relative_preamble = '\n'.join(
+            [(line and '    %s' % (line,) or line)
+             for line in relative_preamble.split('\n')])
+        preamble = relative_preamble + preamble
     addsitepackages_marker = 'def addsitepackages('
     enableusersite_marker = 'ENABLE_USER_SITE = '
     successful_rewrite = False
@@ -1616,7 +1701,8 @@
         %s
         ]
     for path in original_paths:
-        addsitedir(path, known_paths)'''
+        if path == setuptools_path or path not in known_paths:
+            addsitedir(path, known_paths)'''
 
 addsitepackages_script = '''\
 def addsitepackages(known_paths):

Modified: zc.buildout/trunk/src/zc/buildout/easy_install.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/easy_install.txt	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/easy_install.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -1277,6 +1277,7 @@
         """Add site packages, as determined by zc.buildout.
     <BLANKLINE>
         See original_addsitepackages, below, for the original version."""
+        setuptools_path = None
         buildout_paths = [
             '/interpreter/eggs/demo-0.3-pyN.N.egg',
             '/interpreter/eggs/demoneeded-1.1-pyN.N.egg'
@@ -1291,7 +1292,8 @@
             ...
             ]
         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
     <BLANKLINE>
     def original_addsitepackages(known_paths):...
@@ -1368,7 +1370,8 @@
             ...
             ]
         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
     <BLANKLINE>
     def original_addsitepackages(known_paths):...
@@ -1432,7 +1435,8 @@
             ...
             ]
         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
     <BLANKLINE>
     def original_addsitepackages(known_paths):...

Modified: zc.buildout/trunk/src/zc/buildout/testing.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/testing.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/testing.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -596,7 +596,7 @@
     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]+)'''
+        r'''[^'" \t\n\r!]+%(sep)s_[Tt][Ee][Ss][Tt]_%(sep)s([^"' \t\n\r]+)'''
         % dict(sep=sep)),
     _normalize_path,
     )

Modified: zc.buildout/trunk/src/zc/buildout/testing_bugfix.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/testing_bugfix.txt	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/testing_bugfix.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -15,7 +15,7 @@
     >>> len(logging.getLogger().handlers)
     1
     >>> 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:
 
@@ -27,7 +27,7 @@
     >>> len(logging.getLogger().handlers)
     2
     >>> logging.getLogger().handlers # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
-    [<zope.testrunner.logsupport.NullHandler instance at ...>,
+    [<zope...testrunner.logsupport.NullHandler instance at ...>,
      <logging.StreamHandler instance at ...>]
 
 But tear down removes the new logging handler:
@@ -36,4 +36,4 @@
     >>> len(logging.getLogger().handlers)
     1
     >>> logging.getLogger().handlers # doctest: +ELLIPSIS
-    [<zope.testrunner.logsupport.NullHandler instance at ...>]
+    [<zope...testrunner.logsupport.NullHandler instance at ...>]

Modified: zc.buildout/trunk/src/zc/buildout/tests.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/tests.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/tests.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -2255,6 +2255,75 @@
 
     """
 
+def allowed_eggs_from_site_packages_dependencies_bugfix():
+    """
+If you specify that a package with a dependency may come from site-packages,
+that doesn't mean that the dependency may come from site-packages.  This
+is a test for a bug fix to verify that this is true.
+
+    >>> py_path, site_packages_path = make_py()
+    >>> create_sample_sys_install(site_packages_path)
+    >>> interpreter_dir = tmpdir('interpreter')
+    >>> interpreter_parts_dir = os.path.join(
+    ...     interpreter_dir, 'parts', 'interpreter')
+    >>> interpreter_bin_dir = os.path.join(interpreter_dir, 'bin')
+    >>> mkdir(interpreter_bin_dir)
+    >>> mkdir(interpreter_dir, 'eggs')
+    >>> mkdir(interpreter_dir, 'parts')
+    >>> mkdir(interpreter_parts_dir)
+    >>> ws = zc.buildout.easy_install.install(
+    ...     ['demo'], join(interpreter_dir, 'eggs'), executable=py_path,
+    ...     links=[link_server], index=link_server+'index/',
+    ...     allowed_eggs_from_site_packages=['demo'])
+    >>> [dist.project_name for dist in ws]
+    ['demo', 'demoneeded']
+    >>> from pprint import pprint
+    >>> pprint([dist.location for dist in ws])
+    ['/executable_buildout/site-packages',
+     '/interpreter/eggs/demoneeded-1.1-pyN.N.egg']
+
+    """
+
+def allowed_eggs_from_site_packages_bug_592524():
+    """
+When we use allowed_eggs_from_site_packages, we need to make sure that the
+site-packages paths are not inserted with the normal egg paths.  They already
+included at the end, and including them along with the normal egg paths will
+possibly mask subsequent egg paths.  This affects interpreters and scripts
+generated by sitepackage_safe_scripts.
+
+Our "py_path" has the "demoneeded" and "demo" packages available.
+
+    >>> py_path, site_packages_path = make_py()
+    >>> create_sample_sys_install(site_packages_path)
+    >>> interpreter_dir = tmpdir('interpreter')
+    >>> interpreter_parts_dir = os.path.join(
+    ...     interpreter_dir, 'parts', 'interpreter')
+    >>> interpreter_bin_dir = os.path.join(interpreter_dir, 'bin')
+    >>> mkdir(interpreter_bin_dir)
+    >>> mkdir(interpreter_dir, 'eggs')
+    >>> mkdir(interpreter_dir, 'parts')
+    >>> mkdir(interpreter_parts_dir)
+    >>> ws = zc.buildout.easy_install.install(
+    ...     ['demo', 'other'], join(interpreter_dir, 'eggs'), executable=py_path,
+    ...     links=[link_server], index=link_server+'index/',
+    ...     allowed_eggs_from_site_packages=['demo'])
+    >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts(
+    ...     interpreter_bin_dir, ws, py_path, interpreter_parts_dir,
+    ...     interpreter='py', include_site_packages=True)
+
+Now we will look at the paths in the site.py we generated.  Notice that the
+site-packages are at the end.  They were not before this bugfix.
+
+    >>> test = 'import pprint, sys; pprint.pprint(sys.path[-4:])'
+    >>> print call_py(join(interpreter_bin_dir, 'py'), test)
+    ['/interpreter/eggs/other-1.0-pyN.N.egg',
+     '/interpreter/eggs/demoneeded-1.1-pyN.N.egg',
+     '/executable_buildout/eggs/setuptools-0.0-pyN.N.egg',
+     '/executable_buildout/site-packages']
+    <BLANKLINE>
+    """
+
 def subprocesses_have_same_environment_by_default():
     """
 The scripts generated by sitepackage_safe_scripts set the PYTHONPATH so that,
@@ -3057,6 +3126,107 @@
 
     """
 
+def buildout_prefer_final_build_system_option():
+    """
+The accept-buildout-test-releases buildout option can be used for overriding
+the default preference for final distributions for recipes, buildout
+extensions, and buildout itself.  It is usually controlled via the bootstrap
+script rather than in the configuration file, but we will test the machinery
+using the file.
+
+Set up.  This creates sdists for demorecipe 1.0 and 1.1b1, and for
+demoextension 1.0 and 1.1b1.
+
+    >>> create_sample_recipe_sdists(sample_eggs)
+    >>> create_sample_extension_sdists(sample_eggs)
+
+The default is accept-buildout-test-releases = false:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = demo
+    ... find-links = %(link_server)s
+    ... extensions = demoextension
+    ...
+    ... [demo]
+    ... recipe = demorecipe
+    ... ''' % globals())
+
+    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    Installing ...
+    Picked: demoextension = 1.0
+    ...
+    Picked: demorecipe = 1.0
+    ...
+
+Here we see that the final versions of demorecipe and demoextension were used.
+
+We get the same behavior if we explicitly state that
+accept-buildout-test-releases = false.
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = demo
+    ... find-links = %(link_server)s
+    ... extensions = demoextension
+    ... accept-buildout-test-releases = false
+    ...
+    ... [demo]
+    ... recipe = demorecipe
+    ... ''' % globals())
+
+    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    Installing ...
+    Picked: demoextension = 1.0
+    ...
+    Picked: demorecipe = 1.0
+    ...
+
+If we specify accept-buildout-test-releases = true, we'll get the newest
+distributions in the build system:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = demo
+    ... find-links = %(link_server)s
+    ... extensions = demoextension
+    ... accept-buildout-test-releases = true
+    ...
+    ... [demo]
+    ... recipe = demorecipe
+    ... ''' % globals())
+
+    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    Installing ...
+    Picked: demoextension = 1.1b1
+    ...
+    Picked: demorecipe = 1.1b1
+    ...
+
+We get an error if we specify anything but true or false:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = demo
+    ... find-links = %(link_server)s
+    ... extensions = demoextension
+    ... accept-buildout-test-releases = no
+    ...
+    ... [demo]
+    ... recipe = demorecipe
+    ... ''' % globals())
+
+    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    While:
+      Initializing.
+    Error: Invalid value for accept-buildout-test-releases option: no
+
+    """
+
 def develop_with_modules():
     """
 Distribution setup scripts can import modules in the distribution directory:
@@ -3423,6 +3593,68 @@
         finally:
             shutil.rmtree(tmp)
 
+def create_sample_extension_sdists(dest):
+    from zc.buildout.testing import write, mkdir
+    name = 'demoextension'
+    for version in ('1.0', '1.1b1'):
+        tmp = tempfile.mkdtemp()
+        try:
+            write(tmp, 'README.txt', '')
+            write(tmp, name + '.py',
+                  "def ext(buildout):\n"
+                  "    pass\n"
+                  "def unload(buildout):\n"
+                  "    pass\n"
+                  % locals())
+            write(tmp, 'setup.py',
+                  "from setuptools import setup\n"
+                  "setup(\n"
+                  "    name = %(name)r,\n"
+                  "    py_modules = [%(name)r],\n"
+                  "    entry_points = {\n"
+                  "       'zc.buildout.extension': "
+                              "['ext = %(name)s:ext'],\n"
+                  "       'zc.buildout.unloadextension': "
+                              "['ext = %(name)s:unload'],\n"
+                  "       },\n"
+                  "    zip_safe=True, version=%(version)r,\n"
+                  "    author='bob', url='bob', author_email='bob')\n"
+                  % locals())
+            zc.buildout.testing.sdist(tmp, dest)
+        finally:
+            shutil.rmtree(tmp)
+
+def create_sample_recipe_sdists(dest):
+    from zc.buildout.testing import write, mkdir
+    name = 'demorecipe'
+    for version in ('1.0', '1.1b1'):
+        tmp = tempfile.mkdtemp()
+        try:
+            write(tmp, 'README.txt', '')
+            write(tmp, name + '.py',
+                  "import logging, os, zc.buildout\n"
+                  "class Demorecipe:\n"
+                  "    def __init__(self, buildout, name, options):\n"
+                  "        self.name, self.options = name, options\n"
+                  "    def install(self):\n"
+                  "        return ()\n"
+                  "    def update(self):\n"
+                  "        pass\n"
+                  % locals())
+            write(tmp, 'setup.py',
+                  "from setuptools import setup\n"
+                  "setup(\n"
+                  "    name = %(name)r,\n"
+                  "    py_modules = [%(name)r],\n"
+                  "    entry_points = {'zc.buildout': "
+                                       "['default = %(name)s:Demorecipe']},\n"
+                  "    zip_safe=True, version=%(version)r,\n"
+                  "    author='bob', url='bob', author_email='bob')\n"
+                  % locals())
+            zc.buildout.testing.sdist(tmp, dest)
+        finally:
+            shutil.rmtree(tmp)
+
 def _write_eggrecipedemoneeded(tmp, minor_version, suffix=''):
     from zc.buildout.testing import write
     write(tmp, 'README.txt', '')
@@ -3570,37 +3802,33 @@
 
 egg_parse = re.compile('([0-9a-zA-Z_.]+)-([0-9a-zA-Z_.]+)-py(\d[.]\d).egg$'
                        ).match
-def makeNewRelease(project, ws, dest):
+def makeNewRelease(project, ws, dest, version='99.99'):
     dist = ws.find(pkg_resources.Requirement.parse(project))
     eggname, oldver, pyver = egg_parse(
         os.path.basename(dist.location)
         ).groups()
-    dest = os.path.join(dest, "%s-99.99-py%s.egg" % (eggname, pyver))
+    dest = os.path.join(dest, "%s-%s-py%s.egg" % (eggname, version, pyver))
     if os.path.isfile(dist.location):
         shutil.copy(dist.location, dest)
         zip = zipfile.ZipFile(dest, 'a')
         zip.writestr(
             'EGG-INFO/PKG-INFO',
             zip.read('EGG-INFO/PKG-INFO').replace("Version: %s" % oldver,
-                                                  "Version: 99.99")
+                                                  "Version: %s" % version)
             )
         zip.close()
     else:
         shutil.copytree(dist.location, dest)
         info_path = os.path.join(dest, 'EGG-INFO', 'PKG-INFO')
         info = open(info_path).read().replace("Version: %s" % oldver,
-                                              "Version: 99.99")
+                                              "Version: %s" % version)
         open(info_path, 'w').write(info)
 
-
-def updateSetup(test):
-    zc.buildout.testing.buildoutSetUp(test)
-    new_releases = test.globs['tmpdir']('new_releases')
-    test.globs['new_releases'] = new_releases
+def getWorkingSetWithBuildoutEgg(test):
     sample_buildout = test.globs['sample_buildout']
     eggs = os.path.join(sample_buildout, 'eggs')
 
-    # If the zc.buildout dist is a develo dist, convert it to a
+    # If the zc.buildout dist is a develop dist, convert it to a
     # regular egg in the sample buildout
     req = pkg_resources.Requirement.parse('zc.buildout')
     dist = pkg_resources.working_set.find(req)
@@ -3630,9 +3858,16 @@
             os.path.join(sample_buildout, 'bin'))
     else:
         ws = pkg_resources.working_set
+    return ws
 
+def updateSetup(test):
+    zc.buildout.testing.buildoutSetUp(test)
+    new_releases = test.globs['tmpdir']('new_releases')
+    test.globs['new_releases'] = new_releases
+    ws = getWorkingSetWithBuildoutEgg(test)
     # now let's make the new releases
     makeNewRelease('zc.buildout', ws, new_releases)
+    makeNewRelease('zc.buildout', ws, new_releases, '100.0b1')
     os.mkdir(os.path.join(new_releases, 'zc.buildout'))
     if zc.buildout.easy_install.is_distribute:
         makeNewRelease('distribute', ws, new_releases)
@@ -3641,6 +3876,13 @@
         makeNewRelease('setuptools', ws, new_releases)
         os.mkdir(os.path.join(new_releases, 'setuptools'))
 
+def bootstrapSetup(test):
+    easy_install_SetUp(test)
+    sample_eggs = test.globs['sample_eggs']
+    ws = getWorkingSetWithBuildoutEgg(test)
+    makeNewRelease('zc.buildout', ws, sample_eggs)
+    makeNewRelease('zc.buildout', ws, sample_eggs, '100.0b1')
+    os.environ['bootstrap-testing-find-links'] = test.globs['link_server']
 
 normalize_bang = (
     re.compile(re.escape('#!'+
@@ -3648,6 +3890,19 @@
     '#!/usr/local/bin/python2.4',
     )
 
+hide_distribute_additions = (re.compile('install_dir .+\n'), '')
+hide_zip_safe_message = (
+    # This comes in a different place in the output in Python 2.7.  It's not
+    # important to our tests.  Hide it.
+    re.compile(
+        '((?<=\n)\n)?zip_safe flag not set; analyzing archive contents...\n'),
+    '')
+hide_first_index_page_message = (
+    # This comes in a different place in the output in Python 2.7.  It's not
+    # important to our tests.  Hide it.
+    re.compile(
+        "Couldn't find index page for '[^']+' \(maybe misspelled\?\)\n"),
+    '')
 def test_suite():
     test_suite = [
         doctest.DocFileSuite(
@@ -3655,44 +3910,47 @@
             setUp=zc.buildout.testing.buildoutSetUp,
             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,
-               (re.compile('__buildout_signature__ = recipes-\S+'),
-                '__buildout_signature__ = recipes-SSSSSSSSSSS'),
-               (re.compile('executable = [\S ]+python\S*', re.I),
-                'executable = python'),
-               (re.compile('[-d]  (setuptools|distribute)-\S+[.]egg'),
-                'setuptools.egg'),
-               (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'),
-                'zc.buildout.egg'),
-               (re.compile('creating \S*setup.cfg'), 'creating setup.cfg'),
-               (re.compile('hello\%ssetup' % os.path.sep), 'hello/setup'),
-               (re.compile('Picked: (\S+) = \S+'),
-                'Picked: \\1 = V.V'),
-               (re.compile(r'We have a develop egg: zc.buildout (\S+)'),
-                'We have a develop egg: zc.buildout X.X.'),
-               (re.compile(r'\\[\\]?'), '/'),
-               (re.compile('WindowsError'), 'OSError'),
-               (re.compile(r'\[Error \d+\] Cannot create a file '
-                           r'when that file already exists: '),
-                '[Errno 17] File exists: '
-                ),
-               (re.compile('distribute'), 'setuptools'),
-               ])
+                zc.buildout.testing.normalize_path,
+                zc.buildout.testing.normalize_endings,
+                zc.buildout.testing.normalize_script,
+                zc.buildout.testing.normalize_egg_py,
+                zc.buildout.tests.hide_distribute_additions,
+                hide_zip_safe_message,
+                (re.compile('__buildout_signature__ = recipes-\S+'),
+                 '__buildout_signature__ = recipes-SSSSSSSSSSS'),
+                (re.compile('executable = [\S ]+python\S*', re.I),
+                 'executable = python'),
+                (re.compile('[-d]  (setuptools|distribute)-\S+[.]egg'),
+                 'setuptools.egg'),
+                (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'),
+                 'zc.buildout.egg'),
+                (re.compile('creating \S*setup.cfg'), 'creating setup.cfg'),
+                (re.compile('hello\%ssetup' % os.path.sep), 'hello/setup'),
+                (re.compile('Picked: (\S+) = \S+'),
+                 'Picked: \\1 = V.V'),
+                (re.compile(r'We have a develop egg: zc.buildout (\S+)'),
+                 'We have a develop egg: zc.buildout X.X.'),
+                (re.compile(r'\\[\\]?'), '/'),
+                (re.compile('WindowsError'), 'OSError'),
+                (re.compile(r'\[Error \d+\] Cannot create a file '
+                            r'when that file already exists: '),
+                 '[Errno 17] File exists: '
+                 ),
+                (re.compile('distribute'), 'setuptools'),
+                ])
             ),
         doctest.DocFileSuite(
             'debugging.txt',
             setUp=zc.buildout.testing.buildoutSetUp,
             tearDown=zc.buildout.testing.buildoutTearDown,
             checker=renormalizing.RENormalizing([
-               zc.buildout.testing.normalize_path,
-               zc.buildout.testing.normalize_endings,
-               (re.compile(r'\S+buildout.py'), 'buildout.py'),
-               (re.compile(r'line \d+'), 'line NNN'),
-               (re.compile(r'py\(\d+\)'), 'py(NNN)'),
-               ])
+                zc.buildout.testing.normalize_path,
+                zc.buildout.testing.normalize_endings,
+                zc.buildout.tests.hide_distribute_additions,
+                (re.compile(r'\S+buildout.py'), 'buildout.py'),
+                (re.compile(r'line \d+'), 'line NNN'),
+                (re.compile(r'py\(\d+\)'), 'py(NNN)'),
+                ])
             ),
 
         doctest.DocFileSuite(
@@ -3700,28 +3958,29 @@
             setUp=updateSetup,
             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,
-               normalize_bang,
-               (re.compile('99[.]99'), 'NINETYNINE.NINETYNINE'),
-               (re.compile('(zc.buildout|setuptools)-\d+[.]\d+\S*'
-                           '-py\d.\d.egg'),
-                '\\1.egg'),
-               (re.compile('distribute-\d+[.]\d+\S*'
-                           '-py\d.\d.egg'),
-                'setuptools.egg'),
-               (re.compile('(zc.buildout|setuptools)( version)? \d+[.]\d+\S*'),
-                '\\1 V.V'),
-               (re.compile('distribute( version)? \d+[.]\d+\S*'),
-                'setuptools V.V'),
-               (re.compile('[-d]  (setuptools|distribute)'), '-  setuptools'),
-               (re.compile('distribute'), 'setuptools'),
-               (re.compile("\nUnused options for buildout: "
-                           "'(distribute|setuptools)\-version'\."),
-                '')
-               ])
+                zc.buildout.testing.normalize_path,
+                zc.buildout.testing.normalize_endings,
+                zc.buildout.testing.normalize_script,
+                zc.buildout.testing.normalize_egg_py,
+                normalize_bang,
+                zc.buildout.tests.hide_distribute_additions,
+                (re.compile('99[.]99'), 'NINETYNINE.NINETYNINE'),
+                (re.compile('(zc.buildout|setuptools)-\d+[.]\d+\S*'
+                            '-py\d.\d.egg'),
+                 '\\1.egg'),
+                (re.compile('distribute-\d+[.]\d+\S*'
+                            '-py\d.\d.egg'),
+                 'setuptools.egg'),
+                (re.compile('(zc.buildout|setuptools)( version)? \d+[.]\d+\S*'),
+                 '\\1 V.V'),
+                (re.compile('distribute( version)? \d+[.]\d+\S*'),
+                 'setuptools V.V'),
+                (re.compile('[-d]  (setuptools|distribute)'), '-  setuptools'),
+                (re.compile('distribute'), 'setuptools'),
+                (re.compile("\nUnused options for buildout: "
+                            "'(distribute|setuptools)\-version'\."),
+                 '')
+                ])
             ),
 
         doctest.DocFileSuite(
@@ -3730,28 +3989,30 @@
             setUp=easy_install_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,
-               normalize_bang,
-               (re.compile('extdemo[.]pyd'), 'extdemo.so'),
-               (re.compile('[-d]  (setuptools|distribute)-\S+[.]egg'),
-                'setuptools.egg'),
-               (re.compile(r'\\[\\]?'), '/'),
-               (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)'),
-               (re.compile('distribute'), 'setuptools'),
-               # Distribute unzips eggs by default.
-               (re.compile('\-  demoneeded'), 'd  demoneeded'),
-               ]+(sys.version_info < (2, 5) and [
-                  (re.compile('.*No module named runpy.*', re.S), ''),
-                  (re.compile('.*usage: pdb.py scriptfile .*', re.S), ''),
-                  (re.compile('.*Error: what does not exist.*', re.S), ''),
-                  ] or [])),
+                zc.buildout.testing.normalize_path,
+                zc.buildout.testing.normalize_endings,
+                zc.buildout.testing.normalize_script,
+                zc.buildout.testing.normalize_egg_py,
+                normalize_bang,
+                hide_first_index_page_message,
+                zc.buildout.tests.hide_distribute_additions,
+                (re.compile('extdemo[.]pyd'), 'extdemo.so'),
+                (re.compile('[-d]  (setuptools|distribute)-\S+[.]egg'),
+                 'setuptools.egg'),
+                (re.compile(r'\\[\\]?'), '/'),
+                (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)'),
+                (re.compile('distribute'), 'setuptools'),
+                # Distribute unzips eggs by default.
+                (re.compile('\-  demoneeded'), 'd  demoneeded'),
+                ]+(sys.version_info < (2, 5) and [
+                   (re.compile('.*No module named runpy.*', re.S), ''),
+                   (re.compile('.*usage: pdb.py scriptfile .*', re.S), ''),
+                   (re.compile('.*Error: what does not exist.*', re.S), ''),
+                   ] or [])),
             ),
 
         doctest.DocFileSuite(
@@ -3772,35 +4033,37 @@
             setUp=easy_install_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,
-               (re.compile("buildout: Running \S*setup.py"),
-                'buildout: Running setup.py'),
-               (re.compile('(setuptools|distribute)-\S+-'),
-                'setuptools.egg'),
-               (re.compile('zc.buildout-\S+-'),
-                'zc.buildout.egg'),
-               (re.compile('File "\S+one.py"'),
-                'File "one.py"'),
-               (re.compile(r'We have a develop egg: (\S+) (\S+)'),
-                r'We have a develop egg: \1 V'),
-               (re.compile('Picked: (setuptools|distribute) = \S+'),
-                'Picked: setuptools = V'),
-               (re.compile(r'\\[\\]?'), '/'),
-               (re.compile(
-                   '-q develop -mxN -d "/sample-buildout/develop-eggs'),
-                   '-q develop -mxN -d /sample-buildout/develop-eggs'
-                ),
-               (re.compile(r'^[*]...'), '...'),
-               # for bug_92891_bootstrap_crashes_with_egg_recipe_in_buildout_section
-               (re.compile(r"Unused options for buildout: 'eggs' 'scripts'\."),
-                "Unused options for buildout: 'scripts' 'eggs'."),
-               (re.compile('distribute'), 'setuptools'),
-               # Distribute unzips eggs by default.
-               (re.compile('\-  demoneeded'), 'd  demoneeded'),
-               ]),
+                zc.buildout.testing.normalize_path,
+                zc.buildout.testing.normalize_endings,
+                zc.buildout.testing.normalize_script,
+                zc.buildout.testing.normalize_egg_py,
+                zc.buildout.tests.hide_distribute_additions,
+                hide_first_index_page_message,
+                (re.compile("buildout: Running \S*setup.py"),
+                 'buildout: Running setup.py'),
+                (re.compile('(setuptools|distribute)-\S+-'),
+                 'setuptools.egg'),
+                (re.compile('zc.buildout-\S+-'),
+                 'zc.buildout.egg'),
+                (re.compile('File "\S+one.py"'),
+                 'File "one.py"'),
+                (re.compile(r'We have a develop egg: (\S+) (\S+)'),
+                 r'We have a develop egg: \1 V'),
+                (re.compile('Picked: (setuptools|distribute) = \S+'),
+                 'Picked: setuptools = V'),
+                (re.compile(r'\\[\\]?'), '/'),
+                (re.compile(
+                    '-q develop -mxN -d "/sample-buildout/develop-eggs'),
+                    '-q develop -mxN -d /sample-buildout/develop-eggs'
+                 ),
+                (re.compile(r'^[*]...'), '...'),
+                # for bug_92891_bootstrap_crashes_with_egg_recipe_in_buildout_section
+                (re.compile(r"Unused options for buildout: 'eggs' 'scripts'\."),
+                 "Unused options for buildout: 'scripts' 'eggs'."),
+                (re.compile('distribute'), 'setuptools'),
+                # Distribute unzips eggs by default.
+                (re.compile('\-  demoneeded'), 'd  demoneeded'),
+                ]),
             ),
         zc.buildout.testselectingpython.test_suite(),
         zc.buildout.rmtree.test_suite(),
@@ -3809,31 +4072,42 @@
             setUp=zc.buildout.testing.buildoutSetUp,
             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,
-               (re.compile('__buildout_signature__ = recipes-\S+'),
-                '__buildout_signature__ = recipes-SSSSSSSSSSS'),
-               (re.compile('[-d]  setuptools-\S+[.]egg'), 'setuptools.egg'),
-               (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'),
-                'zc.buildout.egg'),
-               (re.compile('creating \S*setup.cfg'), 'creating setup.cfg'),
-               (re.compile('hello\%ssetup' % os.path.sep), 'hello/setup'),
-               (re.compile('Picked: (\S+) = \S+'),
-                'Picked: \\1 = V.V'),
-               (re.compile(r'We have a develop egg: zc.buildout (\S+)'),
-                'We have a develop egg: zc.buildout X.X.'),
-               (re.compile(r'\\[\\]?'), '/'),
-               (re.compile('WindowsError'), 'OSError'),
-               (re.compile(r'\[Error 17\] Cannot create a file '
-                           r'when that file already exists: '),
-                '[Errno 17] File exists: '
-                ),
-               ])
+                zc.buildout.testing.normalize_path,
+                zc.buildout.testing.normalize_endings,
+                zc.buildout.testing.normalize_script,
+                zc.buildout.testing.normalize_egg_py,
+                zc.buildout.tests.hide_distribute_additions,
+                (re.compile('__buildout_signature__ = recipes-\S+'),
+                 '__buildout_signature__ = recipes-SSSSSSSSSSS'),
+                (re.compile('[-d]  setuptools-\S+[.]egg'), 'setuptools.egg'),
+                (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'),
+                 'zc.buildout.egg'),
+                (re.compile('creating \S*setup.cfg'), 'creating setup.cfg'),
+                (re.compile('hello\%ssetup' % os.path.sep), 'hello/setup'),
+                (re.compile('Picked: (\S+) = \S+'),
+                 'Picked: \\1 = V.V'),
+                (re.compile(r'We have a develop egg: zc.buildout (\S+)'),
+                 'We have a develop egg: zc.buildout X.X.'),
+                (re.compile(r'\\[\\]?'), '/'),
+                (re.compile('WindowsError'), 'OSError'),
+                (re.compile(r'\[Error 17\] Cannot create a file '
+                            r'when that file already exists: '),
+                 '[Errno 17] File exists: '
+                 ),
+                ])
             ),
         doctest.DocFileSuite(
-            'testing_bugfix.txt'),
+            'testing_bugfix.txt',
+            checker=renormalizing.RENormalizing([
+                # Python 2.7
+                (re.compile(
+                    re.escape(
+                        'testrunner.logsupport.NullHandler instance at')),
+                 'testrunner.logsupport.NullHandler object at'),
+                (re.compile(re.escape('logging.StreamHandler instance at')),
+                 'logging.StreamHandler object at'),
+                ])
+            ),
     ]
 
     # adding bootstrap.txt doctest to the suite
@@ -3851,17 +4125,38 @@
     if os.path.exists(bootstrap_py):
         test_suite.append(doctest.DocFileSuite(
             'bootstrap.txt',
+            setUp=bootstrapSetup,
+            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,
+                normalize_bang,
+                (re.compile('Downloading.*setuptools.*egg\n'), ''),
+                (re.compile('options:'), 'Options:'),
+                (re.compile('usage:'), 'Usage:'),
+                ]),
+            ))
+        test_suite.append(doctest.DocFileSuite(
+            'virtualenv.txt',
             setUp=easy_install_SetUp,
             tearDown=zc.buildout.testing.buildoutTearDown,
             checker=renormalizing.RENormalizing([
-               zc.buildout.testing.normalize_path,
-               zc.buildout.testing.normalize_endings,
-               zc.buildout.testing.normalize_script,
-               normalize_bang,
-               (re.compile('Downloading.*setuptools.*egg\n'), ''),
-               (re.compile('options:'), 'Options:'),
-               (re.compile('usage:'), 'Usage:'),
-               ]),
+                zc.buildout.testing.normalize_path,
+                zc.buildout.testing.normalize_endings,
+                zc.buildout.testing.normalize_script,
+                zc.buildout.testing.normalize_egg_py,
+                zc.buildout.tests.hide_distribute_additions,
+                (re.compile('(setuptools|distribute)-\S+-'),
+                 'setuptools.egg'),
+                (re.compile('zc.buildout-\S+-'),
+                 'zc.buildout.egg'),
+                (re.compile(re.escape('#!"/executable_buildout/bin/py"')),
+                 '#!/executable_buildout/bin/py'), # Windows.
+                (re.compile(re.escape('/broken_s/')),
+                 '/broken_S/'), # Windows.
+                ]),
             ))
 
     return unittest.TestSuite(test_suite)

Modified: zc.buildout/trunk/src/zc/buildout/update.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/update.txt	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/src/zc/buildout/update.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -3,13 +3,14 @@
 
 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,
-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:
 
     >>> ls(new_releases)
     d  setuptools
     -  setuptools-99.99-py2.4.egg
     d  zc.buildout
+    -  zc.buildout-100.0b1-pyN.N.egg
     -  zc.buildout-99.99-py2.4.egg
 
 Let's update the sample buildout.cfg to look in this area:
@@ -78,6 +79,13 @@
     zc.buildout 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:
 
     >>> cat(sample_buildout, 'parts', 'buildout', 'site.py')
@@ -162,7 +170,7 @@
     setuptools 0.6
 
 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:
 
     >>> sample_buildout2 = tmpdir('sample_buildout2')
@@ -187,3 +195,57 @@
     Not upgrading because not running a local buildout command.
 
     >>> 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.')
+    ...

Copied: zc.buildout/trunk/src/zc/buildout/virtualenv.txt (from rev 115859, zc.buildout/branches/gary-betafix/src/zc/buildout/virtualenv.txt)
===================================================================
--- zc.buildout/trunk/src/zc/buildout/virtualenv.txt	                        (rev 0)
+++ zc.buildout/trunk/src/zc/buildout/virtualenv.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -0,0 +1,259 @@
+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',
+        ]
+    ...
+

Modified: zc.buildout/trunk/z3c.recipe.scripts_/CHANGES.txt
===================================================================
--- zc.buildout/trunk/z3c.recipe.scripts_/CHANGES.txt	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/z3c.recipe.scripts_/CHANGES.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -1,6 +1,11 @@
 Change History
 **************
 
+1.0.0 (unreleased)
+==================
+
+(no significant changes)
+
 1.0.0b1 (2010-04-29)
 ====================
 

Copied: zc.buildout/trunk/z3c.recipe.scripts_/MANIFEST.in (from rev 115859, zc.buildout/branches/gary-betafix/z3c.recipe.scripts_/MANIFEST.in)
===================================================================
--- zc.buildout/trunk/z3c.recipe.scripts_/MANIFEST.in	                        (rev 0)
+++ zc.buildout/trunk/z3c.recipe.scripts_/MANIFEST.in	2010-08-23 15:04:24 UTC (rev 115887)
@@ -0,0 +1,3 @@
+include *.txt
+recursive-include src *.txt
+exclude MANIFEST.in buildout.cfg .bzrignore

Modified: zc.buildout/trunk/z3c.recipe.scripts_/setup.py
===================================================================
--- zc.buildout/trunk/z3c.recipe.scripts_/setup.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/z3c.recipe.scripts_/setup.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -12,11 +12,9 @@
 #
 ##############################################################################
 """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
 from setuptools import setup, find_packages
@@ -60,8 +58,8 @@
     package_dir = {'':'src'},
     namespace_packages = ['z3c', 'z3c.recipe'],
     install_requires = [
-        'zc.buildout >=1.5.0dev',
-        'zc.recipe.egg >=1.2.3dev',
+        'zc.buildout >=1.5.0',
+        'zc.recipe.egg >=1.3.0',
         'setuptools'],
     tests_require = ['zope.testing'],
     test_suite = name+'.tests.test_suite',

Modified: zc.buildout/trunk/z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py
===================================================================
--- zc.buildout/trunk/z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -35,23 +35,13 @@
             '*')
         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',
-            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')
+            default=b_options.get('include-site-packages', 'false'))
 
-        value = options.setdefault(
+        self.exec_sitecustomize = options.query_bool(
             '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')
+            default=b_options.get('exec-sitecustomize', 'false'))
 
 
 class Interpreter(Base):

Modified: zc.buildout/trunk/z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py
===================================================================
--- zc.buildout/trunk/z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -416,24 +416,26 @@
             '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|distribute)-[^-]+-'), 'setuptools-X-'),
-               (re.compile(r'(setuptools|distribute)-[\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)'),
-               (re.compile('distribute'), 'setuptools'),
-               ])
+                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,
+                zc.buildout.tests.hide_distribute_additions,
+                zc.buildout.tests.hide_first_index_page_message,
+                (re.compile(r'zc.buildout(-\S+)?[.]egg(-link)?'),
+                 'zc.buildout.egg'),
+                (re.compile('[-d]  (setuptools|distribute)-[^-]+-'), 'setuptools-X-'),
+                (re.compile(r'(setuptools|distribute)-[\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)'),
+                (re.compile('distribute'), 'setuptools'),
+                ])
             ),
         doctest.DocTestSuite(
             setUp=setUp,
@@ -442,6 +444,8 @@
                 zc.buildout.testing.normalize_path,
                 zc.buildout.testing.normalize_endings,
                 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'),
                 ]),
             ),

Modified: zc.buildout/trunk/zc.recipe.egg_/CHANGES.txt
===================================================================
--- zc.buildout/trunk/zc.recipe.egg_/CHANGES.txt	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/zc.recipe.egg_/CHANGES.txt	2010-08-23 15:04:24 UTC (rev 115887)
@@ -1,6 +1,12 @@
 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)
 ====================
 

Copied: zc.buildout/trunk/zc.recipe.egg_/MANIFEST.in (from rev 115859, zc.buildout/branches/gary-betafix/zc.recipe.egg_/MANIFEST.in)
===================================================================
--- zc.buildout/trunk/zc.recipe.egg_/MANIFEST.in	                        (rev 0)
+++ zc.buildout/trunk/zc.recipe.egg_/MANIFEST.in	2010-08-23 15:04:24 UTC (rev 115887)
@@ -0,0 +1,3 @@
+include *.txt
+recursive-include src *.txt
+exclude MANIFEST.in buildout.cfg .bzrignore

Modified: zc.buildout/trunk/zc.recipe.egg_/setup.py
===================================================================
--- zc.buildout/trunk/zc.recipe.egg_/setup.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/zc.recipe.egg_/setup.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -12,11 +12,9 @@
 #
 ##############################################################################
 """Setup for zc.recipe.egg package
-
-$Id$
 """
 
-version = '1.2.3dev'
+version = '1.3.0'
 
 import os
 from setuptools import setup, find_packages
@@ -66,7 +64,7 @@
     package_dir = {'':'src'},
     namespace_packages = ['zc', 'zc.recipe'],
     install_requires = [
-        'zc.buildout >=1.5.0dev',
+        'zc.buildout >=1.5.0',
         'setuptools'],
     tests_require = ['zope.testing'],
     test_suite = name+'.tests.test_suite',

Modified: zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/egg.py
===================================================================
--- zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/egg.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/egg.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -52,9 +52,6 @@
         options['develop-eggs-directory'] = b_options['develop-eggs-directory']
         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'])
         options['executable'] = buildout[python]['executable']
 
@@ -84,7 +81,7 @@
         else:
             kw = {}
             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(
                 distributions, options['eggs-directory'],
                 links=self.links,
@@ -159,7 +156,7 @@
                     raise zc.buildout.UserError("Invalid entry point")
                 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,
                 # except setuptools.
                 reqs = list(reqs)
@@ -192,17 +189,4 @@
             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

Modified: zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/tests.py
===================================================================
--- zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/tests.py	2010-08-23 14:55:43 UTC (rev 115886)
+++ zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/tests.py	2010-08-23 15:04:24 UTC (rev 115887)
@@ -43,54 +43,58 @@
             '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('zc.buildout(-\S+)?[.]egg(-link)?'),
-                'zc.buildout.egg'),
-               (re.compile('[-d]  (setuptools|distribute)-[^-]+-'),
-                'setuptools-X-'),
-               (re.compile(r'eggs\\\\demo'), 'eggs/demo'),
-               (re.compile(r'[a-zA-Z]:\\\\foo\\\\bar'), '/foo/bar'),
-               # Distribute unzips eggs by default.
-               (re.compile('\-  demoneeded'), 'd  demoneeded'),
-               ])
+                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,
+                zc.buildout.tests.hide_distribute_additions,
+                (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'),
+                 'zc.buildout.egg'),
+                (re.compile('[-d]  (setuptools|distribute)-[^-]+-'),
+                 'setuptools-X-'),
+                (re.compile(r'eggs\\\\demo'), 'eggs/demo'),
+                (re.compile(r'[a-zA-Z]:\\\\foo\\\\bar'), '/foo/bar'),
+                # Distribute unzips eggs by default.
+                (re.compile('\-  demoneeded'), 'd  demoneeded'),
+                ])
             ),
         doctest.DocFileSuite(
             'api.txt',
             setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown,
             checker=renormalizing.RENormalizing([
-               zc.buildout.testing.normalize_path,
-               zc.buildout.testing.normalize_endings,
-               (re.compile('__buildout_signature__ = '
-                           'sample-\S+\s+'
-                           'zc.recipe.egg-\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),
-                'executable = python'),
-               (re.compile('find-links = http://localhost:\d+/'),
-                'find-links = http://localhost:8080/'),
-               (re.compile('index = http://localhost:\d+/index'),
-                'index = http://localhost:8080/index'),
-               ])
+                zc.buildout.testing.normalize_path,
+                zc.buildout.testing.normalize_endings,
+                zc.buildout.tests.hide_distribute_additions,
+                (re.compile('__buildout_signature__ = '
+                            'sample-\S+\s+'
+                            'zc.recipe.egg-\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),
+                 'executable = python'),
+                (re.compile('find-links = http://localhost:\d+/'),
+                 'find-links = http://localhost:8080/'),
+                (re.compile('index = http://localhost:\d+/index'),
+                 'index = http://localhost:8080/index'),
+                ])
             ),
         doctest.DocFileSuite(
             'custom.txt',
             setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown,
             checker=renormalizing.RENormalizing([
-               zc.buildout.testing.normalize_path,
-               zc.buildout.testing.normalize_endings,
-               (re.compile("(d  ((ext)?demo(needed)?|other)"
-                           "-\d[.]\d-py)\d[.]\d(-\S+)?[.]egg"),
-                '\\1V.V.egg'),
-               (re.compile('extdemo.c\n.+\\extdemo.exp\n'), ''),
-               (re.compile('extdemo[.]pyd'), 'extdemo.so')
-               ]),
+                zc.buildout.testing.normalize_path,
+                zc.buildout.testing.normalize_endings,
+                zc.buildout.tests.hide_distribute_additions,
+                zc.buildout.tests.hide_zip_safe_message,
+                (re.compile("(d  ((ext)?demo(needed)?|other)"
+                            "-\d[.]\d-py)\d[.]\d(-\S+)?[.]egg"),
+                 '\\1V.V.egg'),
+                (re.compile('extdemo.c\n.+\\extdemo.exp\n'), ''),
+                (re.compile('extdemo[.]pyd'), 'extdemo.so')
+                ]),
             ),
 
         ))
@@ -104,21 +108,22 @@
                 setUp=setUpSelecting,
                 tearDown=zc.buildout.testing.buildoutTearDown,
                 checker=renormalizing.RENormalizing([
-                   zc.buildout.testing.normalize_path,
-                   zc.buildout.testing.normalize_endings,
-                   zc.buildout.testing.normalize_script,
-                   (re.compile('Got (setuptools|distribute) \S+'),
-                    'Got setuptools V'),
-                   (re.compile('([d-]  )?(setuptools|distribute)-\S+-py'),
-                    'setuptools-V-py'),
-                   (re.compile('-py2[.][0-35-9][.]'), 'py2.5.'),
-                   (re.compile('zc.buildout-\S+[.]egg'),
-                    'zc.buildout.egg'),
-                   (re.compile('zc.buildout[.]egg-link'),
-                    'zc.buildout.egg'),
-                   # Distribute unzips eggs by default.
-                   (re.compile('\-  demoneeded'), 'd  demoneeded'),
-                   ]),
+                    zc.buildout.testing.normalize_path,
+                    zc.buildout.testing.normalize_endings,
+                    zc.buildout.testing.normalize_script,
+                    zc.buildout.tests.hide_distribute_additions,
+                    (re.compile('Got (setuptools|distribute) \S+'),
+                     'Got setuptools V'),
+                    (re.compile('([d-]  )?(setuptools|distribute)-\S+-py'),
+                     'setuptools-V-py'),
+                    (re.compile('-py2[.][0-35-9][.]'), 'py2.5.'),
+                    (re.compile('zc.buildout-\S+[.]egg'),
+                     'zc.buildout.egg'),
+                    (re.compile('zc.buildout[.]egg-link'),
+                     'zc.buildout.egg'),
+                    # Distribute unzips eggs by default.
+                    (re.compile('\-  demoneeded'), 'd  demoneeded'),
+                    ]),
                 ),
             )
 



More information about the checkins mailing list