[Checkins] SVN: zc.buildout/branches/gary-support-system-python/ Three new features for using a system Python, and some cleanup.

Gary Poster gary.poster at canonical.com
Tue Aug 4 19:11:53 EDT 2009


Log message for revision 102487:
  Three new features for using a system Python, and some cleanup.
  
  - Add new option and tests: ``allowed-eggs-from-site-packages`` allows you
    to specify a glob-aware whitelist of project names that may come from
    site-packages.  This defaults to '*', meaning there is no filtering.
  - Add feature and test to let you see what eggs have been selected from
    site-packages: "Egg from site-packages: ..." in the output of
    ``bin/buildout -v``.
  - Add new option and tests: ``include-site-packages-for-buildout`` allows
    you to control if site-packages are used for the bin/buildout script.
    This defaults to "false," which is a change in behavior!  (Rationale is in
    docs.)
  - Standardize on one of the several competing approaches for default options
    in the [buildout] section.
  - Add comment about recipes using buildout options, not buildout attributes.
    Practice what I preach in zc.recipe.egg.
  - Standardize on one approach for handling bool options in zc.recipe.egg.  Not
    sure I like it but it is preexisting, and now it is consistent, and it
    behaves well in terms of letting buildout be configured before it looks too
    hard at it.
  - Normalize tests.py function docstrings to begin at col 0
  - Correct some typos
  
  
  

Changed:
  U   zc.buildout/branches/gary-support-system-python/src/zc/buildout/buildout.py
  U   zc.buildout/branches/gary-support-system-python/src/zc/buildout/buildout.txt
  U   zc.buildout/branches/gary-support-system-python/src/zc/buildout/easy_install.py
  U   zc.buildout/branches/gary-support-system-python/src/zc/buildout/testing.py
  U   zc.buildout/branches/gary-support-system-python/src/zc/buildout/tests.py
  U   zc.buildout/branches/gary-support-system-python/zc.recipe.egg_/src/zc/recipe/egg/egg.py

-=-
Modified: zc.buildout/branches/gary-support-system-python/src/zc/buildout/buildout.py
===================================================================
--- zc.buildout/branches/gary-support-system-python/src/zc/buildout/buildout.py	2009-08-04 13:48:58 UTC (rev 102486)
+++ zc.buildout/branches/gary-support-system-python/src/zc/buildout/buildout.py	2009-08-04 23:11:53 UTC (rev 102487)
@@ -66,15 +66,27 @@
         return "The referenced section, %r, was not defined." % self[0]
 
 _buildout_default_options = {
+    'allow-hosts': '*',
+    'allow-picked-versions': 'true',
+    'allowed-eggs-from-site-packages': '*',
+    'bin-directory': 'bin',
+    'develop-eggs-directory': 'develop-eggs',
     'eggs-directory': 'eggs',
-    'develop-eggs-directory': 'develop-eggs',
-    'bin-directory': 'bin',
+    'executable': sys.executable,
+    'find-links': '',
+    'include-site-packages-for-buildout': 'false',
+    'include-site-packages': 'true',
+    'install-from-cache': 'false',
+    'installed': '.installed.cfg',
+    'log-format': '',
+    'log-level': 'INFO',
+    'newest': 'true',
+    'offline': 'false',
     'parts-directory': 'parts',
-    'installed': '.installed.cfg',
+    'prefer-final': 'false',
     'python': 'buildout',
-    'executable': sys.executable,
-    'log-level': 'INFO',
-    'log-format': '',
+    'unzip': 'false',
+    'use-dependency-links': 'true',
     }
 
 class Buildout(UserDict.DictMixin):
@@ -98,7 +110,7 @@
                     print 'Creating %r.' % config_file
                     open(config_file, 'w').write('[buildout]\nparts = \n')
                 elif command == 'setup':
-                    # Sigh. this model of a buildout nstance
+                    # Sigh. this model of a buildout instance
                     # with methods is breaking down :(
                     config_file = None
                     data['buildout']['directory'] = '.'
@@ -137,7 +149,7 @@
         # provide some defaults before options are parsed
         # because while parsing options those attributes might be
         # used already (Gottfried Ganssauge)
-        buildout_section = data.get('buildout')
+        buildout_section = data['buildout']
 
         # Try to make sure we have absolute paths for standard
         # directories. We do this before doing substitutions, in case
@@ -150,22 +162,29 @@
                 d = self._buildout_path(buildout_section[name+'-directory'])
                 buildout_section[name+'-directory'] = d
 
-        links = buildout_section and buildout_section.get('find-links', '')
+        # Arguably, these attributes shouldn't be used by recipes.  Using
+        # attributes on the buildout causes bugs when a buildout is extended,
+        # potentially overriding these values; and yet the option is read from
+        # this attribute during the initialization of the recipes (see
+        # ``options = self['buildout']`` below) before the full processing
+        # is completed.  These attributes are left behind for legacy support
+        # but recipe authors should beware of using them.  A better practice is
+        # for a recipe to read the buildout['buildout'] options.
+        links = buildout_section['find-links']
         self._links = links and links.split() or ()
-
-        allow_hosts = buildout_section and buildout_section.get(
-             'allow-hosts', '*').split('\n')
+        allow_hosts = buildout_section['allow-hosts'].split('\n')
         self._allow_hosts = tuple([host.strip() for host in allow_hosts
                                    if host.strip() != ''])
-
         self._logger = logging.getLogger('zc.buildout')
-        self.offline = False
-        self.newest = True
+        self.offline = buildout_section['offline'] == 'true'
+        self.newest = buildout_section['newest'] == 'true'
 
         ##################################################################
         ## WARNING!!!
         ## ALL ATTRIBUTES MUST HAVE REASONABLE DEFAULTS AT THIS POINT
-        ## OTHERWISE ATTRIBUTEERRORS MIGHT HAPPEN ANY TIME
+        ## OTHERWISE ATTRIBUTEERRORS MIGHT HAPPEN ANY TIME FROM RECIPES.
+        ## RECIPES SHOULD GENERALLY USE buildout['buildout'] OPTIONS, NOT
+        ## BUILDOUT ATTRIBUTES.
         ##################################################################
         # initialize some attrs and buildout directories.
         options = self['buildout']
@@ -174,7 +193,7 @@
         links = options.get('find-links', '')
         self._links = links and links.split() or ()
 
-        allow_hosts = options.get('allow-hosts', '*').split('\n')
+        allow_hosts = options.setdefault('allow-hosts', '*').split('\n')
         self._allow_hosts = tuple([host.strip() for host in allow_hosts
                                    if host.strip() != ''])
 
@@ -192,49 +211,60 @@
 
         self._setup_logging()
 
-        offline = options.get('offline', 'false')
+        offline = options['offline']
         if offline not in ('true', 'false'):
             self._error('Invalid value for offline option: %s', offline)
-        options['offline'] = offline
-        self.offline = offline == 'true'
+        self.offline = (offline == 'true')
 
         if self.offline:
             newest = options['newest'] = 'false'
         else:
-            newest = options.get('newest', 'true')
+            newest = options['newest']
             if newest not in ('true', 'false'):
                 self._error('Invalid value for newest option: %s', newest)
-            options['newest'] = newest
-        self.newest = newest == 'true'
+        self.newest = (newest == 'true')
 
         versions = options.get('versions')
         if versions:
             zc.buildout.easy_install.default_versions(dict(self[versions]))
 
-        prefer_final = options.setdefault('prefer-final', 'false')
+        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')
 
-        include_site_packages = options.setdefault(
-            'include-site-packages', 'true')
+        include_site_packages = options['include-site-packages']
         if include_site_packages not in ('true', 'false'):
             self._error('Invalid value for include-site-packages option: %s',
                         include_site_packages)
         zc.buildout.easy_install.include_site_packages(
             include_site_packages=='true')
 
-        use_dependency_links = options.setdefault(
-            'use-dependency-links', 'true')
+        allowed_eggs_from_site_packages = tuple(
+            name.strip() for name in
+            options['allowed-eggs-from-site-packages'].split('\n'))
+        zc.buildout.easy_install.allowed_eggs_from_site_packages(
+            allowed_eggs_from_site_packages)
+
+        include_site_packages_for_buildout = options[
+            'include-site-packages-for-buildout']
+        if include_site_packages_for_buildout not in ('true', 'false'):
+            self._error(
+                'Invalid value for include-site-packages-for-buildout option: '
+                '%s',
+                 include_site_packages_for_buildout)
+        self.include_site_packages_for_buildout = (
+            include_site_packages_for_buildout=='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)
         zc.buildout.easy_install.use_dependency_links(
             use_dependency_links=='true')
 
-        allow_picked_versions = options.setdefault(
-            'allow-picked-versions', '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)
@@ -256,15 +286,14 @@
 
             zc.buildout.easy_install.download_cache(download_cache)
 
-        install_from_cache = options.setdefault(
-            'install-from-cache', 'false')
+        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.setdefault('unzip', 'false')
+        always_unzip = options['unzip']
         if always_unzip not in ('true', 'false'):
             self._error('Invalid value for unzip option: %s',
                         always_unzip)
@@ -294,7 +323,8 @@
         if options.get('offline') == 'true':
             ws = zc.buildout.easy_install.working_set(
                 distributions, options['executable'],
-                [options['develop-eggs-directory'], options['eggs-directory']]
+                [options['develop-eggs-directory'], options['eggs-directory']],
+                include_site_packages=self.include_site_packages_for_buildout
                 )
         else:
             ws = zc.buildout.easy_install.install(
@@ -304,7 +334,9 @@
                 executable=options['executable'],
                 path=[options['develop-eggs-directory']],
                 newest=self.newest,
-                allow_hosts=self._allow_hosts,)
+                allow_hosts=self._allow_hosts,
+                include_site_packages=self.include_site_packages_for_buildout
+                )
 
         # Now copy buildout and setuptools eggs, and record destination eggs:
         entries = []

Modified: zc.buildout/branches/gary-support-system-python/src/zc/buildout/buildout.txt
===================================================================
--- zc.buildout/branches/gary-support-system-python/src/zc/buildout/buildout.txt	2009-08-04 13:48:58 UTC (rev 102486)
+++ zc.buildout/branches/gary-support-system-python/src/zc/buildout/buildout.txt	2009-08-04 23:11:53 UTC (rev 102487)
@@ -2023,19 +2023,23 @@
 
     >>> print system(buildout+' -vv'),
     Installing 'zc.buildout', 'setuptools'.
-    We have a develop egg: zc.buildout 1.0.0.
+    We have a develop egg: zc.buildout X.X.
     We have the best distribution that satisfies 'setuptools'.
-    Picked: setuptools = 0.6
+    Picked: setuptools = V.V
     <BLANKLINE>
     Configuration data:
     [buildout]
+    allow-hosts = *
     allow-picked-versions = true
+    allowed-eggs-from-site-packages = *
     bin-directory = /sample-buildout/bin
     develop-eggs-directory = /sample-buildout/develop-eggs
     directory = /sample-buildout
     eggs-directory = /sample-buildout/eggs
-    executable = /usr/local/bin/python2.3
+    executable = python
+    find-links = 
     include-site-packages = true
+    include-site-packages-for-buildout = false
     install-from-cache = false
     installed = /sample-buildout/.installed.cfg
     log-format = 
@@ -2055,6 +2059,29 @@
 command-line assignments.  We've discussed most of these options
 already, but let's review them and touch on some we haven't discussed:
 
+allow-hosts
+    On some environments the links visited by `zc.buildout` can be forbidden by
+    paranoid firewalls. These URLs might be in the chain of links visited by
+    `zc.buildout` as defined by buildout's `find-links` option, or as defined
+    by various eggs in their `url`, `download_url`, `dependency_links` metadata.
+    
+    The fact that package_index works like a spider and might visit links and
+    go to other locations makes this even harder.
+    
+    The `allow-hosts` option provides a way to prevent this, and
+    works exactly like the one provided in `easy_install`.
+    
+    You can provide a list of allowed host, together with wildcards::
+    
+        [buildout]
+        ...
+    
+        allow-hosts =
+            *.python.org
+            example.com
+    
+    All URLs that does not match these hosts will not be visited.
+
 allow-picked-versions
     By default, the buildout will choose the best match for a given requirement
     if the requirement is not specified precisely (for instance, using the
@@ -2063,6 +2090,35 @@
     "allow-picked-versions" is "false," instead of picking the best match,
     buildout will raise an error.  This helps enforce repeatability.
 
+allowed-eggs-from-site-packages
+    Sometimes you need or want to control what eggs from site-packages are
+    used. The allowed-eggs-from-site-packages option allows you to specify a
+    whitelist of project names that may be included from site-packages.  You
+    can use globs to specify the value.  It defaults to a single value of '*',
+    indicating that any package may come from site-packages.
+
+    Here's a usage example::
+    
+        [buildout]
+        ...
+    
+        allowed-eggs-from-site-packages =
+            demo
+            bigdemo
+            zope.*
+
+    This option interacts with the ``include-site-packages`` option in the
+    following ways.
+    
+    If ``include-site-packages`` is true, then
+    ``allowed-eggs-from-site-packages`` filters what eggs from site-packages
+    may be chosen.  Therefore, if ``allowed-eggs-from-site-packages`` is an
+    empty list, then no eggs from site-packages are chosen, but site-packages
+    will still be included at the end of path lists.
+    
+    If ``include-site-packages`` is false, the value of
+    ``allowed-eggs-from-site-packages`` is irrelevant.
+
 bin-directory
    The directory path where scripts are written.  This can be a
    relative path, which is interpreted relative to the directory
@@ -2087,6 +2143,38 @@
    The Python executable used to run the buildout.  See the python
    option below.
 
+find-links
+    You can specify more locations to search for distributions using the
+    `find-links` option. All locations specified will be searched for
+    distributions along with the package index as described before.
+    
+    Locations can be urls::
+    
+      [buildout]
+      ...
+      find-links = http://download.zope.org/distribution/
+    
+    They can also be directories on disk::
+    
+      [buildout]
+      ...
+      find-links = /some/path
+    
+    Finally, they can also be direct paths to distributions::
+    
+      [buildout]
+      ...
+      find-links = /some/path/someegg-1.0.0-py2.3.egg
+    
+    Any number of locations can be specified in the `find-links` option::
+    
+      [buildout]
+      ...
+      find-links =
+          http://download.zope.org/distribution/
+          /some/otherpath
+          /some/path/someegg-1.0.0-py2.3.egg
+
 include-site-packages
     By default, buildout will look for dependencies in the system's
     site-packages.  For this purpose, paths outside of Python's standard
@@ -2096,6 +2184,27 @@
     the default behavior of using site packages
     ("include-site-packages = false").
 
+include-site-packages-for-buildout
+    When buildout gets a recipe egg (as opposed to runs a recipe), it starts
+    with the current Python working set--the one that the bin/buildout script
+    uses itself. If this working set includes site-packages, and site-packages
+    includes an egg for a package that the recipe needs, *and* the recipe
+    specifies a newer version of that package, this can generate a version
+    conflict.
+    
+    One solution to this is to not use site-packages
+    (``include-site-packages = false``).  However, if you want your scripts to
+    use site-packages, then you have to specify 'include-site-packages = true'
+    for all of them.
+    
+    To make this use case easier to handle, you can instead specify
+    ``include-site-packages-with-buildout = false``, which indicates that the
+    bin/buildout should *not* use site-packages; and
+    ``include-site-packages = true``, which indicates that the rest of the
+    scripts should use site-packages.
+    
+    This is the default configuration.
+
 install-from-cache
     A download cache can be used as the basis of application source releases. 
     In an application source release, we want to distribute an application that
@@ -2197,7 +2306,6 @@
    A log-level adjustment.  Typically, this is set via the -q and -v
    command-line options.
 
-
 Creating new buildouts and bootstrapping
 ----------------------------------------
 
@@ -2209,6 +2317,7 @@
 
     >>> print system(buildout
     ...              +' -c'+os.path.join(sample_bootstrapped, 'setup.cfg')
+    ...              +' buildout:include-site-packages-for-buildout=true'
     ...              +' init'),
     Creating '/sample-bootstrapped/setup.cfg'.
     Creating directory '/sample-bootstrapped/bin'.
@@ -2246,23 +2355,25 @@
 normally use the bootstrap command instead of init.  It will complain
 if there isn't a configuration file:
 
-     >>> sample_bootstrapped2 = tmpdir('sample-bootstrapped2')
+    >>> sample_bootstrapped2 = tmpdir('sample-bootstrapped2')
 
-     >>> print system(buildout
-     ...              +' -c'+os.path.join(sample_bootstrapped2, 'setup.cfg')
-     ...              +' bootstrap'),
-     While:
-       Initializing.
-     Error: Couldn't open /sample-bootstrapped2/setup.cfg
+    >>> print system(buildout
+    ...              +' -c'+os.path.join(sample_bootstrapped2, 'setup.cfg')
+    ...              +' buildout:include-site-packages-for-buildout=true'
+    ...              +' bootstrap'),
+    While:
+      Initializing.
+    Error: Couldn't open /sample-bootstrapped2/setup.cfg
 
-     >>> write(sample_bootstrapped2, 'setup.cfg',
-     ... """
-     ... [buildout]
-     ... parts =
-     ... """)
+    >>> write(sample_bootstrapped2, 'setup.cfg',
+    ... """
+    ... [buildout]
+    ... parts =
+    ... """)
 
     >>> print system(buildout
     ...              +' -c'+os.path.join(sample_bootstrapped2, 'setup.cfg')
+    ...              +' buildout:include-site-packages-for-buildout=true'
     ...              +' bootstrap'),
     Creating directory '/sample-bootstrapped2/bin'.
     Creating directory '/sample-bootstrapped2/parts'.
@@ -2270,7 +2381,6 @@
     Creating directory '/sample-bootstrapped2/develop-eggs'.
     Generated script '/sample-bootstrapped2/bin/buildout'.
 
-
 Finding distributions
 ---------------------
 
@@ -2289,37 +2399,9 @@
 requirements of the buildout will always be used.
 
 You can also specify more locations to search for distributions using
-the `find-links` option. All locations specified will be searched for
-distributions along with the package index as described before.
+the `find-links` option. See its description above.
 
-Locations can be urls::
 
-  [buildout]
-  ...
-  find-links = http://download.zope.org/distribution/
-
-They can also be directories on disk::
-
-  [buildout]
-  ...
-  find-links = /some/path
-
-Finally, they can also be direct paths to distributions::
-
-  [buildout]
-  ...
-  find-links = /some/path/someegg-1.0.0-py2.3.egg
-
-Any number of locations can be specified in the `find-links` option::
-
-  [buildout]
-  ...
-  find-links =
-      http://download.zope.org/distribution/
-      /some/otherpath
-      /some/path/someegg-1.0.0-py2.3.egg
-
-
 Controlling the installation database
 -------------------------------------
 
@@ -2481,32 +2563,6 @@
     Develop: '/sample-bootstrapped/demo'
     unload ['buildout']
 
-Allow hosts
------------
-
-On some environments the links visited by `zc.buildout` can be forbidden
-by paranoiac firewalls. These URL might be on the chain of links
-visited by `zc.buildout` wheter they are defined in the `find-links` option,
-wheter they are defined by various eggs in their `url`, `download_url`,
-`dependency_links` metadata.
-
-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
-works exactly like the one provided in `easy_install`.
-
-You can provide a list of allowed host, together with wildcards::
-
-    [buildout]
-    ...
-
-    allow-hosts =
-        *.python.org
-        example.com
-
-All urls that does not match these hosts will not be visited.
-
 .. [#future_recipe_methods] In the future, additional methods may be
        added. Older recipes with fewer methods will still be
        supported.

Modified: zc.buildout/branches/gary-support-system-python/src/zc/buildout/easy_install.py
===================================================================
--- zc.buildout/branches/gary-support-system-python/src/zc/buildout/easy_install.py	2009-08-04 13:48:58 UTC (rev 102486)
+++ zc.buildout/branches/gary-support-system-python/src/zc/buildout/easy_install.py	2009-08-04 23:11:53 UTC (rev 102487)
@@ -21,6 +21,7 @@
 """
 
 import distutils.errors
+import fnmatch
 import glob
 import logging
 import os
@@ -202,6 +203,7 @@
     _allow_picked_versions = True
     _always_unzip = False
     _include_site_packages = True
+    _allowed_eggs_from_site_packages = ('*',)
 
     def __init__(self,
                  dest=None,
@@ -214,6 +216,7 @@
                  versions=None,
                  use_dependency_links=None,
                  include_site_packages=None,
+                 allowed_eggs_from_site_packages=None,
                  allow_hosts=('*',)
                  ):
         self._dest = dest
@@ -239,6 +242,9 @@
         path = (path and path[:] or [])
         if include_site_packages is not None:
             self._include_site_packages = include_site_packages
+        if allowed_eggs_from_site_packages is not None:
+            self._allowed_eggs_from_site_packages = tuple(
+                allowed_eggs_from_site_packages)
         stdlib, self._site_packages = _get_system_packages(executable)
         if self._include_site_packages:
             path.extend(buildout_and_setuptools_path)
@@ -260,18 +266,34 @@
         if versions is not None:
             self._versions = versions
 
+    _allowed_eggs_from_site_packages_regex = None
+    def allow_site_package_egg(self, name):
+        if (not self._include_site_packages or
+            not self._allowed_eggs_from_site_packages):
+            # If the answer is a blanket "no," perform a shortcut.
+            return False
+        if self._allowed_eggs_from_site_packages_regex is None:
+            pattern = '(%s)' % (
+                '|'.join(
+                    fnmatch.translate(name)
+                    for name in self._allowed_eggs_from_site_packages),
+                )
+            self._allowed_eggs_from_site_packages_regex = re.compile(pattern)
+        return bool(self._allowed_eggs_from_site_packages_regex.match(name))
+
     def _satisfied(self, req, source=None):
-        # We get all distributions that match the given requirement.  If we
-        # are not supposed to include site-packages, we also filter those out.
-        # We need to do the filtering here even though we have exluded
-        # site packages from the _env's paths (see Installer.__init__) because
-        # an .egg-link, such as one for setuptools or zc.buildout installed
-        # by zc.buildout.buildout.Buildout.bootstrap, can indirectly include
-        # a path in our _site_packages.
+        # We get all distributions that match the given requirement.  If we are
+        # not supposed to include site-packages for the given egg, we also
+        # filter those out. Even if include_site_packages is False and so we
+        # have excluded site packages from the _env's paths (see
+        # Installer.__init__), we need to do the filtering here because an
+        # .egg-link, such as one for setuptools or zc.buildout installed by
+        # zc.buildout.buildout.Buildout.bootstrap, can indirectly include a
+        # path in our _site_packages.
         dists = [dist for dist in self._env[req.project_name] if (
                     dist in req and (
-                        self._include_site_packages or
-                        dist.location not in self._site_packages)
+                        dist.location not in self._site_packages or
+                        self.allow_site_package_egg(dist.project_name))
                     )
                 ]
         if not dists:
@@ -477,18 +499,19 @@
             # Nothing is available.
             return None
 
-        # Filter the available dists for the requirement and source flag. If we
-        # are not supposed to include site-packages, we also filter those out.
-        # We need to do the filtering here even though we have exluded site
-        # packages from the _index's paths (see Installer.__init__) because an
+        # Filter the available dists for the requirement and source flag.  If
+        # we are not supposed to include site-packages for the given egg, we
+        # also filter those out. Even if include_site_packages is False and so
+        # we have excluded site packages from the _env's paths (see
+        # Installer.__init__), we need to do the filtering here because an
         # .egg-link, such as one for setuptools or zc.buildout installed by
         # zc.buildout.buildout.Buildout.bootstrap, can indirectly include a
         # path in our _site_packages.
         dists = [dist for dist in index[requirement.project_name]
                  if ((dist in requirement)
                      and
-                     (self._include_site_packages or
-                      dist.location not in self._site_packages)
+                     (dist.location not in self._site_packages or
+                      self.allow_site_package_egg(dist.project_name))
                      and
                      ((not source) or
                       (dist.precedence == pkg_resources.SOURCE_DIST)
@@ -778,6 +801,8 @@
                     pkg_resources.VersionConflict(dist, req), ws)
             requirements.extend(dist.requires(req.extras)[::-1])
             processed[req] = True
+            if dist.location in self._site_packages:
+                logger.debug('Egg from site-packages: %s', dist)
 
         return ws
 
@@ -879,6 +904,12 @@
         Installer._include_site_packages = bool(setting)
     return old
 
+def allowed_eggs_from_site_packages(setting=None):
+    old = Installer._allowed_eggs_from_site_packages
+    if setting is not None:
+        Installer._allowed_eggs_from_site_packages = tuple(setting)
+    return old
+
 def use_dependency_links(setting=None):
     old = Installer._use_dependency_links
     if setting is not None:
@@ -902,10 +933,12 @@
             executable=sys.executable, always_unzip=None,
             path=None, working_set=None, newest=True, versions=None,
             use_dependency_links=None, include_site_packages=None,
-            allow_hosts=('*',)):
+            allowed_eggs_from_site_packages=None, allow_hosts=('*',)):
     installer = Installer(dest, links, index, executable, always_unzip, path,
                           newest, versions, use_dependency_links,
-                          include_site_packages, allow_hosts=allow_hosts)
+                          include_site_packages,
+                          allowed_eggs_from_site_packages,
+                          allow_hosts=allow_hosts)
     return installer.install(specs, working_set)
 
 
@@ -913,9 +946,11 @@
           links=(), index=None,
           executable=sys.executable,
           path=None, newest=True, versions=None, include_site_packages=None,
-          allow_hosts=('*',)):
+          allowed_eggs_from_site_packages=None, allow_hosts=('*',)):
     installer = Installer(dest, links, index, executable, True, path, newest,
-                          versions, include_site_packages, allow_hosts=allow_hosts)
+                          versions, include_site_packages,
+                          allowed_eggs_from_site_packages,
+                          allow_hosts=allow_hosts)
     return installer.build(spec, build_ext)
 
 
@@ -1011,10 +1046,12 @@
         [f() for f in undo]
 
 
-def working_set(specs, executable, path, include_site_packages=None):
+def working_set(specs, executable, path, include_site_packages=None,
+                allowed_eggs_from_site_packages=None):
     return install(
         specs, None, executable=executable, path=path,
-        include_site_packages=include_site_packages)
+        include_site_packages=include_site_packages,
+        allowed_eggs_from_site_packages=allowed_eggs_from_site_packages)
 
 def get_path(working_set, executable, extra_paths=(),
              include_site_packages=True):

Modified: zc.buildout/branches/gary-support-system-python/src/zc/buildout/testing.py
===================================================================
--- zc.buildout/branches/gary-support-system-python/src/zc/buildout/testing.py	2009-08-04 13:48:58 UTC (rev 102486)
+++ zc.buildout/branches/gary-support-system-python/src/zc/buildout/testing.py	2009-08-04 23:11:53 UTC (rev 102487)
@@ -278,6 +278,8 @@
          # trick bootstrap into putting the buildout develop egg
          # in the eggs dir.
          ('buildout', 'develop-eggs-directory', 'eggs'),
+         # we need to have setuptools around.
+         ('buildout', 'include-site-packages-for-buildout', 'true'),
          ]
         ).bootstrap([])
 

Modified: zc.buildout/branches/gary-support-system-python/src/zc/buildout/tests.py
===================================================================
--- zc.buildout/branches/gary-support-system-python/src/zc/buildout/tests.py	2009-08-04 13:48:58 UTC (rev 102486)
+++ zc.buildout/branches/gary-support-system-python/src/zc/buildout/tests.py	2009-08-04 23:11:53 UTC (rev 102487)
@@ -11,7 +11,7 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""XXX short summary goes here.
+"""Tests, test set up, and hook-up for stand-alone doctests.
 
 $Id$
 """
@@ -258,18 +258,17 @@
 
 def show_who_requires_when_there_is_a_conflict():
     """
-    It's a pain when we require eggs that have requirements that are
-    incompatible. We want the error we get to tell us what is missing.
+It's a pain when we require eggs that have requirements that are incompatible.
+We want the error we get to tell us what is missing.
 
-    Let's make a few develop distros, some of which have incompatible
-    requirements.
+Let's make a few develop distros, some of which have incompatible requirements.
 
     >>> make_dist_that_requires(sample_buildout, 'sampley',
     ...                         ['demoneeded ==1.0'])
     >>> make_dist_that_requires(sample_buildout, 'samplez',
     ...                         ['demoneeded ==1.1'])
 
-    Now, let's create a buildout that requires y and z:
+Now, let's create a buildout that requires y and z:
 
     >>> write('buildout.cfg',
     ... '''
@@ -315,7 +314,7 @@
     ...        samplez
     ... ''' % globals())
 
-If we use the verbose switch, we can see where requirements are comning from:
+If we use the verbose switch, we can see where requirements are coming from:
 
     >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
     Installing 'zc.buildout', 'setuptools'.
@@ -348,12 +347,10 @@
 
 def show_who_requires_missing_distributions():
     """
+When working with a lot of eggs, which require eggs recursively, it can be hard
+to tell why we're requireing things we can't find. Fortunately, buildout will
+tell us who's asking for something that we can't find.
 
-    When working with a lot of eggs, which require eggs recursively,
-    it can be hard to tell why we're requireing things we can't find.
-    Fortunately, buildout will tell us who's asking for something that
-    we can't find.
-
     >>> make_dist_that_requires(sample_buildout, 'sampley', ['demoneeded'])
     >>> make_dist_that_requires(sample_buildout, 'samplea', ['sampleb'])
     >>> make_dist_that_requires(sample_buildout, 'sampleb',
@@ -382,11 +379,75 @@
     Error: Couldn't find a distribution for 'demoneeded'.
     """
 
+def show_eggs_from_site_packages():
+    """
+Sometimes you want to know what eggs are coming from site-packages.  This
+might be for a diagnostic, or so that you can get a starting value for the
+allowed-eggs-from-site-packages option.  The -v flag will also include this
+information.
 
+Our "primed_executable" has the "demoneeded," "other," and "setuptools"
+packages available.  We'll ask for "other" and "bigdemo".
+
+Here's our set up.
+
+    >>> primed_executable = get_executable_with_site_packages()
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = eggs
+    ... prefer-final = true
+    ... find-links = %(link_server)s
+    ...
+    ... [primed_python]
+    ... executable = %(primed_executable)s
+    ...
+    ... [eggs]
+    ... recipe = zc.recipe.egg:eggs
+    ... python = primed_python
+    ... eggs = other
+    ...        bigdemo
+    ... ''' % globals())
+
+Now here is the output.  The lines that begin with "Egg from site-packages:"
+indicate the eggs from site-packages that have been selected.  You'll see
+we have two: other 1.0 and demoneeded 1.1.
+
+    >>> print system(primed_executable+" "+buildout+" -v")
+    Installing 'zc.buildout', 'setuptools'.
+    We have a develop egg: zc.buildout V
+    We have the best distribution that satisfies 'setuptools'.
+    Picked: setuptools = V
+    Installing 'zc.recipe.egg'.
+    We have a develop egg: zc.recipe.egg V
+    Installing eggs.
+    Installing 'other', 'bigdemo'.
+    We have the best distribution that satisfies 'other'.
+    Picked: other = 1.0
+    We have no distributions for bigdemo that satisfies 'bigdemo'.
+    Getting distribution for 'bigdemo'.
+    Got bigdemo 0.1.
+    Picked: bigdemo = 0.1
+    Egg from site-packages: other 1.0
+    Getting required 'demo'
+      required by bigdemo 0.1.
+    We have no distributions for demo that satisfies 'demo'.
+    Getting distribution for 'demo'.
+    Got demo 0.3.
+    Picked: demo = 0.3
+    Getting required 'demoneeded'
+      required by demo 0.3.
+    We have the best distribution that satisfies 'demoneeded'.
+    Picked: demoneeded = 1.1
+    Egg from site-packages: demoneeded 1.1
+    <BLANKLINE>
+
+    """
+
 def test_comparing_saved_options_with_funny_characters():
     """
-    If an option has newlines, extra/odd spaces or a %, we need to make
-    sure the comparison with the saved value works correctly.
+If an option has newlines, extra/odd spaces or a %, we need to make sure the
+comparison with the saved value works correctly.
 
     >>> mkdir(sample_buildout, 'recipes')
     >>> write(sample_buildout, 'recipes', 'debug.py',
@@ -604,6 +665,7 @@
 
     >>> os.chdir(d)
     >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')
+    ...              + ' buildout:include-site-packages-for-buildout=true'
     ...              + ' bootstrap'),
     Creating directory '/sample-bootstrap/bin'.
     Creating directory '/sample-bootstrap/parts'.
@@ -631,6 +693,7 @@
 
     >>> os.chdir(d)
     >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')
+    ...              + ' buildout:include-site-packages-for-buildout=true'
     ...              + ' bootstrap'),
     Creating directory '/sample-bootstrap/bin'.
     Creating directory '/sample-bootstrap/parts'.
@@ -1805,6 +1868,8 @@
     ...      # trick bootstrap into putting the buildout develop egg
     ...      # in the eggs dir.
     ...      ('buildout', 'develop-eggs-directory', 'eggs'),
+    ...      # we need to have setuptools around.
+    ...      ('buildout', 'include-site-packages-for-buildout', 'true'),
     ...     ]
     ...     ).bootstrap([])
     >>> os.mkdir('develop-eggs')
@@ -2594,6 +2659,376 @@
 
     """
 
+def include_site_packages_with_buildout():
+    """
+When buildout gets a recipe egg (as opposed to runs a recipe), it starts with
+the current Python working set--the one that the bin/buildout script uses
+itself. If this working set includes site-packages, and site-packages includes
+an egg for package that the recipe needs, and the recipe specifies a newer
+version of that package, this can generate a version conflict.
+
+One solution to this is to not use site-packages
+('include-site-packages = false').  However, if you want your scripts to use
+site-packages, then you have to specify 'include-site-packages = true' for
+all of them.
+
+To make this use case easier to handle, you can instead specify
+``include-site-packages-with-buildout = false``, which indicates that
+the bin/buildout should *not* use site-packages; and
+``include-site-packages = true``, which indicates that the rest of the scripts
+should use site-packages.
+
+This is the default configuration.
+
+    >>> from zc.buildout.buildout import Buildout
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... find-links = %(link_server)s
+    ... ''' % globals())
+    >>> buildout = Buildout('buildout.cfg', ())
+    >>> buildout['buildout']['include-site-packages-for-buildout']
+    'false'
+    >>> buildout['buildout']['include-site-packages']
+    'true'
+    >>> buildout.include_site_packages_for_buildout
+    False
+    >>> zc.buildout.easy_install.include_site_packages()
+    True
+
+This means that, when the buildout script is created by buildout, it explicitly
+specifies that site-packages should not be used.  We'll monkeypatch the
+zc.buildout.easy_install install function so we can see this happens.  (We test
+that this argument actually does what we want in other tests.)
+
+    >>> original_install = zc.buildout.easy_install.install
+    >>> def install(*args, **kwargs):
+    ...     print 'include_site_packages =', kwargs['include_site_packages']
+    ...     return original_install(*args, **kwargs)
+    ...
+    >>> zc.buildout.easy_install.install = install
+    >>> buildout.bootstrap(()) # doctest: +ELLIPSIS
+    include_site_packages = False...
+
+Now we'll do the reverse settings to show that the value will be honored in
+that case.
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... include-site-packages-for-buildout = true
+    ... include-site-packages = false
+    ... find-links = %(link_server)s
+    ... ''' % globals())
+    >>> buildout = Buildout('buildout.cfg', ())
+    >>> buildout['buildout']['include-site-packages-for-buildout']
+    'true'
+    >>> buildout['buildout']['include-site-packages']
+    'false'
+    >>> buildout.include_site_packages_for_buildout
+    True
+    >>> zc.buildout.easy_install.include_site_packages()
+    False
+    >>> buildout.bootstrap(()) # doctest: +ELLIPSIS
+    include_site_packages = True...
+    >>> zc.buildout.easy_install.install = original_install
+
+Now we'll show that a value that is not 'true' or 'false' generates an error.
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... include-site-packages-for-buildout = shazbot
+    ... ''')
+    >>> buildout = Buildout('buildout.cfg', ())
+    Traceback (most recent call last):
+    ...
+    UserError: Invalid value for include-site-packages-for-buildout option: shazbot
+
+    """
+
+def allowed_eggs_from_site_packages():
+    """
+Sometimes you need or want to control what eggs from site-packages are used.
+The allowed-eggs-from-site-packages option allows you to specify a whitelist of
+project names that may be included from site-packages.  You can use globs to
+specify the value.  It defaults to a single value of '*', indicating that any
+package may come from site-packages.
+
+This option interacts with include-site-packages in the following ways.
+
+If include-site-packages is true, then allowed-eggs-from-site-packages filters
+what eggs from site-packages may be chosen.  If allowed-eggs-from-site-packages
+is an empty list, then no eggs from site-packages are chosen, but site-packages
+will still be included at the end of path lists.
+
+If include-site-packages is false, allowed-eggs-from-site-packages is
+irrelevant.
+
+This test shows the interaction with the zc.buildout.easy_install API.  Another
+test below (allow_site_package_eggs_option) shows using it with a buildout.cfg.
+
+Our "primed_executable" has the "demoneeded," "other," and "setuptools"
+packages available.  We'll simply be asking for "other" here.
+
+    >>> primed_executable = get_executable_with_site_packages()
+
+    >>> example_dest = tmpdir('site-packages-example-install')
+    >>> workingset = zc.buildout.easy_install.install(
+    ...     ['other'], example_dest, links=[], executable=primed_executable,
+    ...     index=None,
+    ...     allowed_eggs_from_site_packages=['demoneeded', 'other'])
+    >>> [dist.project_name for dist in workingset]
+    ['other']
+
+That worked fine.  It would work fine for a glob too.
+
+    >>> zc.buildout.easy_install.clear_index_cache()
+    >>> rmdir(example_dest)
+    >>> example_dest = tmpdir('site-packages-example-install')
+    >>> workingset = zc.buildout.easy_install.install(
+    ...     ['other'], example_dest, links=[], executable=primed_executable,
+    ...     index=None,
+    ...     allowed_eggs_from_site_packages=['demoneeded', '?th*'])
+    >>> [dist.project_name for dist in workingset]
+    ['other']
+
+But now let's try again with 'other' not allowed.
+
+    >>> zc.buildout.easy_install.clear_index_cache()
+    >>> rmdir(example_dest)
+    >>> example_dest = tmpdir('site-packages-example-install')
+    >>> workingset = zc.buildout.easy_install.install(
+    ...     ['other'], example_dest, links=[], executable=primed_executable,
+    ...     index=None,
+    ...     allowed_eggs_from_site_packages=['demoneeded'])
+    Traceback (most recent call last):
+        ...
+    MissingDistribution: Couldn't find a distribution for 'other'.
+
+Here's the same, but with an empty list.
+
+    >>> zc.buildout.easy_install.clear_index_cache()
+    >>> rmdir(example_dest)
+    >>> example_dest = tmpdir('site-packages-example-install')
+    >>> workingset = zc.buildout.easy_install.install(
+    ...     ['other'], example_dest, links=[], executable=primed_executable,
+    ...     index=None,
+    ...     allowed_eggs_from_site_packages=[])
+    Traceback (most recent call last):
+        ...
+    MissingDistribution: Couldn't find a distribution for 'other'.
+
+Of course, this doesn't stop us from getting a package from elsewhere.  Here,
+we add a link server.
+
+    >>> zc.buildout.easy_install.clear_index_cache()
+    >>> rmdir(example_dest)
+    >>> example_dest = tmpdir('site-packages-example-install')
+    >>> workingset = zc.buildout.easy_install.install(
+    ...     ['other'], example_dest, executable=primed_executable,
+    ...     links=[link_server], index=link_server+'index/',
+    ...     allowed_eggs_from_site_packages=['demoneeded'])
+    >>> [dist.project_name for dist in workingset]
+    ['other']
+    >>> [dist.location for dist in workingset]
+    ['/site-packages-example-install/other-1.0-py2.6.egg']
+
+Finally, here's an example of an interaction we described above: we say that it
+is OK to allow the "other" egg to come from site-packages, but we don't
+include-site-packages.
+
+    >>> zc.buildout.easy_install.clear_index_cache()
+    >>> rmdir(example_dest)
+    >>> example_dest = tmpdir('site-packages-example-install')
+    >>> workingset = zc.buildout.easy_install.install(
+    ...     ['other'], example_dest, links=[], executable=primed_executable,
+    ...     index=None, include_site_packages=False,
+    ...     allowed_eggs_from_site_packages=['other'])
+    Traceback (most recent call last):
+        ...
+    MissingDistribution: Couldn't find a distribution for 'other'.
+
+    """
+
+def allowed_eggs_from_site_packages_option():
+    """
+As introduced in the previous test, the allowed-eggs-from-site-packages option
+allows you to specify a whitelist of project names that may be included from
+site-packages.
+
+This test shows the option being used in a buildout.
+
+The buildout defaults to a whitelist of ('*',), or any project name.  
+
+    >>> from zc.buildout.buildout import Buildout
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... ''')
+    >>> buildout_instance = Buildout('buildout.cfg', ())
+    >>> buildout_instance['buildout']['allowed-eggs-from-site-packages']
+    '*'
+    >>> zc.buildout.easy_install.allowed_eggs_from_site_packages()
+    ('*',)
+
+Our "primed_executable" has the "demoneeded," "other," and "setuptools"
+packages available.  We'll simply be asking for "other" here.  The default
+value of '*' will allow it.
+
+    >>> primed_executable = get_executable_with_site_packages()
+    >>> zc.buildout.easy_install.clear_index_cache()
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = eggs
+    ... find-links =
+    ... allowed-eggs-from-site-packages = demoneeded
+    ...                                   other
+    ...
+    ... [primed_python]
+    ... executable = %(primed_executable)s
+    ...
+    ... [eggs]
+    ... recipe = zc.recipe.egg:eggs
+    ... python = primed_python
+    ... eggs = other
+    ... ''' % globals())
+
+    >>> print system(primed_executable+" "+buildout)
+    Installing eggs.
+    <BLANKLINE>
+
+Here we explicitly use a "*" for the same result.
+
+    >>> zc.buildout.easy_install.clear_index_cache()
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = eggs
+    ... find-links =
+    ... allowed-eggs-from-site-packages = *
+    ...
+    ... [primed_python]
+    ... executable = %(primed_executable)s
+    ...
+    ... [eggs]
+    ... recipe = zc.recipe.egg:eggs
+    ... python = primed_python
+    ... eggs = other
+    ... ''' % globals())
+
+    >>> print system(primed_executable+" "+buildout)
+    Updating eggs.
+    <BLANKLINE>
+
+Specifying the egg exactly will work as well.
+
+    >>> zc.buildout.easy_install.clear_index_cache()
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = eggs
+    ... find-links =
+    ... allowed-eggs-from-site-packages = demoneeded
+    ...                                   other
+    ...
+    ... [primed_python]
+    ... executable = %(primed_executable)s
+    ...
+    ... [eggs]
+    ... recipe = zc.recipe.egg:eggs
+    ... python = primed_python
+    ... eggs = other
+    ... ''' % globals())
+
+    >>> print system(primed_executable+" "+buildout)
+    Updating eggs.
+    <BLANKLINE>
+
+It will also work if we use a glob ("*" or "?").
+
+    >>> zc.buildout.easy_install.clear_index_cache()
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = eggs
+    ... find-links =
+    ... allowed-eggs-from-site-packages = demoneeded
+    ...                                   ?th*
+    ...
+    ... [primed_python]
+    ... executable = %(primed_executable)s
+    ...
+    ... [eggs]
+    ... recipe = zc.recipe.egg:eggs
+    ... python = primed_python
+    ... eggs = other
+    ... ''' % globals())
+
+    >>> print system(primed_executable+" "+buildout)
+    Updating eggs.
+    <BLANKLINE>
+
+However, if we do not include "other" in the "allowed-eggs-from-site-packages"
+key, we get an error, because the packages are not available in any links, and
+they are not allowed to come from the executable's site packages.
+
+    >>> zc.buildout.easy_install.clear_index_cache()
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = eggs
+    ... find-links =
+    ... allowed-eggs-from-site-packages = demoneeded
+    ...
+    ... [primed_python]
+    ... executable = %(primed_executable)s
+    ...
+    ... [eggs]
+    ... recipe = zc.recipe.egg:eggs
+    ... eggs = other
+    ... ''' % globals())
+    >>> print system(primed_executable+" "+buildout)
+    Uninstalling eggs.
+    Installing eggs.
+    Couldn't find index page for 'other' (maybe misspelled?)
+    Getting distribution for 'other'.
+    While:
+      Installing eggs.
+      Getting distribution for 'other'.
+    Error: Couldn't find a distribution for 'other'.
+    <BLANKLINE>
+
+Finally, here's the same with an empty value.
+
+    >>> zc.buildout.easy_install.clear_index_cache()
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = eggs
+    ... find-links =
+    ... allowed-eggs-from-site-packages =
+    ...
+    ... [primed_python]
+    ... executable = %(primed_executable)s
+    ...
+    ... [eggs]
+    ... recipe = zc.recipe.egg:eggs
+    ... eggs = other
+    ... ''' % globals())
+    >>> print system(primed_executable+" "+buildout)
+    Installing eggs.
+    Couldn't find index page for 'other' (maybe misspelled?)
+    Getting distribution for 'other'.
+    While:
+      Installing eggs.
+      Getting distribution for 'other'.
+    Error: Couldn't find a distribution for 'other'.
+    <BLANKLINE>
+
+    """
+
 def develop_with_modules():
     """
 Distribution setup scripts can import modules in the distribution directory:
@@ -2952,6 +3387,8 @@
              # trick bootstrap into putting the buildout develop egg
              # in the eggs dir.
              ('buildout', 'develop-eggs-directory', 'eggs'),
+             # we need to have setuptools around.
+             ('buildout', 'include-site-packages-for-buildout', 'true'),
             ]
             ).bootstrap([])
         os.mkdir('develop-eggs')
@@ -3148,7 +3585,10 @@
                    '-q develop -mxN -d "/sample-buildout/develop-eggs'),
                    '-q develop -mxN -d /sample-buildout/develop-eggs'
                 ),
-                (re.compile(r'^[*]...'), '...'),
+               (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'."),
                ]),
             ),
         zc.buildout.testselectingpython.test_suite(),

Modified: zc.buildout/branches/gary-support-system-python/zc.recipe.egg_/src/zc/recipe/egg/egg.py
===================================================================
--- zc.buildout/branches/gary-support-system-python/zc.recipe.egg_/src/zc/recipe/egg/egg.py	2009-08-04 13:48:58 UTC (rev 102486)
+++ zc.buildout/branches/gary-support-system-python/zc.recipe.egg_/src/zc/recipe/egg/egg.py	2009-08-04 23:11:53 UTC (rev 102487)
@@ -25,8 +25,8 @@
         self.buildout = buildout
         self.name = name
         self.options = options
-        links = options.get('find-links',
-                            buildout['buildout'].get('find-links'))
+        b_options = buildout['buildout']
+        links = options.get('find-links', b_options['find-links'])
         if links:
             links = links.split()
             options['find-links'] = '\n'.join(links)
@@ -34,33 +34,27 @@
             links = ()
         self.links = links
 
-        index = options.get('index', buildout['buildout'].get('index'))
+        index = options.get('index', b_options.get('index'))
         if index is not None:
             options['index'] = index
         self.index = index
 
-        allow_hosts = buildout['buildout'].get('allow-hosts', '*')
+        allow_hosts = b_options['allow-hosts']
         allow_hosts = tuple([host.strip() for host in allow_hosts.split('\n')
                                if host.strip()!=''])
         self.allow_hosts = allow_hosts 
 
-        options['eggs-directory'] = buildout['buildout']['eggs-directory']
+        options['eggs-directory'] = b_options['eggs-directory']
         options['_e'] = options['eggs-directory'] # backward compat.
-        options['develop-eggs-directory'
-                ] = buildout['buildout']['develop-eggs-directory']
+        options['develop-eggs-directory'] = b_options['develop-eggs-directory']
         options['_d'] = options['develop-eggs-directory'] # backward compat.
 
-        assert options.get('unzip') in ('true', 'false', None)
+        # verify that these are None, 'true' or 'false'
+        get_bool(options, 'unzip')
+        get_bool(options, 'include-site-packages')
 
-        python = options.get('python', buildout['buildout']['python'])
+        python = options.get('python', b_options['python'])
         options['executable'] = buildout[python]['executable']
-        include_site_packages = self.options.get(
-            'include-site-packages',
-            self.buildout['buildout'].get('include-site-packages', 'true'))
-        if include_site_packages not in ('true', 'false'):
-            self._error('Invalid value for include-site-packages option: %s',
-                        include_site_packages)
-        self.include_site_packages = (include_site_packages=='true')
 
     def working_set(self, extra=()):
         """Separate method to just get the working set
@@ -68,6 +62,7 @@
         This is intended for reuse by similar recipes.
         """
         options = self.options
+        b_options = self.buildout['buildout']
 
         distributions = [
             r.strip()
@@ -75,18 +70,24 @@
             if r.strip()]
         orig_distributions = distributions[:]
         distributions.extend(extra)
-
+        kw = {
+            'allowed_eggs_from_site_packages': tuple(
+                name.strip() for name in
+                options.get(
+                    'allowed-eggs-from-site-packages',
+                    b_options['allowed-eggs-from-site-packages']).split('\n'))}
+        if 'include-site-packages' in options:
+            kw['include_site_packages'] = get_bool(
+                options, 'include-site-packages')
         if self.buildout['buildout'].get('offline') == 'true':
             ws = zc.buildout.easy_install.working_set(
                 distributions, options['executable'],
                 [options['develop-eggs-directory'], options['eggs-directory']],
-                include_site_packages=self.include_site_packages
+                **kw
                 )
         else:
-            kw = {}
-            if options.get('unzip'):
+            if 'unzip' in options:
                 kw['always_unzip'] = get_bool(options, 'unzip')
-
             ws = zc.buildout.easy_install.install(
                 distributions, options['eggs-directory'],
                 links=self.links,
@@ -95,7 +96,6 @@
                 path=[options['develop-eggs-directory']],
                 newest=self.buildout['buildout'].get('newest') == 'true',
                 allow_hosts=self.allow_hosts,
-                include_site_packages=self.include_site_packages,
                 **kw)
 
         return orig_distributions, ws
@@ -167,6 +167,10 @@
                     if name != 'setuptools' and name not in reqs:
                         reqs.append(name)
 
+            kw = {}
+            if 'include-site-packages' in options:
+                kw['include_site_packages'] = get_bool(
+                    options, 'include-site-packages')
             return zc.buildout.easy_install.scripts(
                 reqs, ws, options['executable'],
                 options['bin-directory'],
@@ -175,8 +179,8 @@
                 interpreter=options.get('interpreter'),
                 initialization=options.get('initialization', ''),
                 arguments=options.get('arguments', ''),
-                include_site_packages=self.include_site_packages,
-                relative_paths=self._relative_paths
+                relative_paths=self._relative_paths,
+                **kw
                 )
 
         return ()
@@ -193,6 +197,6 @@
         return False
     else:
         raise zc.buildout.UserError(
-            "Invalid value for %s: %s" % (name, value))
+            "Invalid value for %s option: %s" % (name, value))
 
 Egg = Scripts



More information about the Checkins mailing list