eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/easy_install.py
changeset 307 c6bca38c1cbf
equal deleted inserted replaced
306:5ff1fc726848 307:c6bca38c1cbf
       
     1 #############################################################################
       
     2 #
       
     3 # Copyright (c) 2005 Zope Corporation and Contributors.
       
     4 # All Rights Reserved.
       
     5 #
       
     6 # This software is subject to the provisions of the Zope Public License,
       
     7 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
     9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    11 # FOR A PARTICULAR PURPOSE.
       
    12 #
       
    13 ##############################################################################
       
    14 """Python easy_install API
       
    15 
       
    16 This module provides a high-level Python API for installing packages.
       
    17 It doesn't install scripts.  It uses setuptools and requires it to be
       
    18 installed.
       
    19 """
       
    20 
       
    21 import distutils.errors
       
    22 import fnmatch
       
    23 import glob
       
    24 import logging
       
    25 import os
       
    26 import pkg_resources
       
    27 import py_compile
       
    28 import re
       
    29 import setuptools.archive_util
       
    30 import setuptools.command.setopt
       
    31 import setuptools.package_index
       
    32 import shutil
       
    33 import subprocess
       
    34 import sys
       
    35 import tempfile
       
    36 import warnings
       
    37 import zc.buildout
       
    38 import zipimport
       
    39 
       
    40 _oprp = getattr(os.path, 'realpath', lambda path: path)
       
    41 def realpath(path):
       
    42     return os.path.normcase(os.path.abspath(_oprp(path)))
       
    43 
       
    44 default_index_url = os.environ.get(
       
    45     'buildout-testing-index-url',
       
    46     'http://pypi.python.org/simple',
       
    47     )
       
    48 
       
    49 logger = logging.getLogger('zc.buildout.easy_install')
       
    50 
       
    51 url_match = re.compile('[a-z0-9+.-]+://').match
       
    52 
       
    53 is_win32 = sys.platform == 'win32'
       
    54 is_jython = sys.platform.startswith('java')
       
    55 is_distribute = (
       
    56     pkg_resources.Requirement.parse('setuptools').key=='distribute')
       
    57 
       
    58 BROKEN_DASH_S_WARNING = (
       
    59     'Buildout has been asked to exclude or limit site-packages so that '
       
    60     'builds can be repeatable when using a system Python.  However, '
       
    61     'the chosen Python executable has a broken implementation of -S (see '
       
    62     'https://bugs.launchpad.net/virtualenv/+bug/572545 for an example '
       
    63     "problem) and this breaks buildout's ability to isolate site-packages.  "
       
    64     "If the executable already has a clean site-packages (e.g., "
       
    65     "using virtualenv's ``--no-site-packages`` option) you may be getting "
       
    66     'equivalent repeatability.  To silence this warning, use the -s argument '
       
    67     'to the buildout script.  Alternatively, use a Python executable with a '
       
    68     'working -S (such as a standard Python binary).')
       
    69 
       
    70 if is_jython:
       
    71     import java.lang.System
       
    72     jython_os_name = (java.lang.System.getProperties()['os.name']).lower()
       
    73 
       
    74 setuptools_loc = pkg_resources.working_set.find(
       
    75     pkg_resources.Requirement.parse('setuptools')
       
    76     ).location
       
    77 
       
    78 # Include buildout and setuptools eggs in paths.  We prevent dupes just to
       
    79 # keep from duplicating any log messages about them.
       
    80 buildout_loc = pkg_resources.working_set.find(
       
    81     pkg_resources.Requirement.parse('zc.buildout')).location
       
    82 buildout_and_setuptools_path = [setuptools_loc]
       
    83 if os.path.normpath(setuptools_loc) != os.path.normpath(buildout_loc):
       
    84     buildout_and_setuptools_path.append(buildout_loc)
       
    85 
       
    86 def _has_broken_dash_S(executable):
       
    87     """Detect https://bugs.launchpad.net/virtualenv/+bug/572545 ."""
       
    88     # The first attempt here was to simply have the executable attempt to import
       
    89     # ConfigParser and return the return code. That worked except for tests on
       
    90     # Windows, where the return code was wrong for the fake Python executable
       
    91     # generated by the virtualenv.txt test, apparently because setuptools' .exe
       
    92     # file does not pass the -script.py's returncode back properly, at least in
       
    93     # some circumstances. Therefore...print statements.
       
    94     stdout, stderr = subprocess.Popen(
       
    95         [executable, '-Sc',
       
    96          'try:\n'
       
    97          '    import ConfigParser\n'
       
    98          'except ImportError:\n'
       
    99          '    print 1\n'
       
   100          'else:\n'
       
   101          '    print 0\n'],
       
   102         stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
       
   103     return bool(int(stdout.strip()))
       
   104 
       
   105 def _get_system_paths(executable):
       
   106     """Return lists of standard lib and site paths for executable.
       
   107     """
       
   108     # We want to get a list of the site packages, which is not easy.
       
   109     # The canonical way to do this is to use
       
   110     # distutils.sysconfig.get_python_lib(), but that only returns a
       
   111     # single path, which does not reflect reality for many system
       
   112     # Pythons, which have multiple additions.  Instead, we start Python
       
   113     # with -S, which does not import site.py and set up the extra paths
       
   114     # like site-packages or (Ubuntu/Debian) dist-packages and
       
   115     # python-support. We then compare that sys.path with the normal one
       
   116     # (minus user packages if this is Python 2.6, because we don't
       
   117     # support those (yet?).  The set of the normal one minus the set of
       
   118     # the ones in ``python -S`` is the set of packages that are
       
   119     # effectively site-packages.
       
   120     #
       
   121     # The given executable might not be the current executable, so it is
       
   122     # appropriate to do another subprocess to figure out what the
       
   123     # additional site-package paths are. Moreover, even if this
       
   124     # executable *is* the current executable, this code might be run in
       
   125     # the context of code that has manipulated the sys.path--for
       
   126     # instance, to add local zc.buildout or setuptools eggs.
       
   127     def get_sys_path(*args, **kwargs):
       
   128         cmd = [executable]
       
   129         cmd.extend(args)
       
   130         cmd.extend([
       
   131             "-c", "import sys, os;"
       
   132             "print repr([os.path.normpath(p) for p in sys.path if p])"])
       
   133         # Windows needs some (as yet to be determined) part of the real env.
       
   134         env = os.environ.copy()
       
   135         # We need to make sure that PYTHONPATH, which will often be set
       
   136         # to include a custom buildout-generated site.py, is not set, or
       
   137         # else we will not get an accurate sys.path for the executable.
       
   138         env.pop('PYTHONPATH', None)
       
   139         env.update(kwargs)
       
   140         _proc = subprocess.Popen(
       
   141             cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
       
   142         stdout, stderr = _proc.communicate();
       
   143         if _proc.returncode:
       
   144             raise RuntimeError(
       
   145                 'error trying to get system packages:\n%s' % (stderr,))
       
   146         res = eval(stdout.strip())
       
   147         try:
       
   148             res.remove('.')
       
   149         except ValueError:
       
   150             pass
       
   151         return res
       
   152     stdlib = get_sys_path('-S') # stdlib only
       
   153     no_user_paths = get_sys_path(PYTHONNOUSERSITE='x')
       
   154     site_paths = [p for p in no_user_paths if p not in stdlib]
       
   155     return (stdlib, site_paths)
       
   156 
       
   157 def _get_version_info(executable):
       
   158     cmd = [executable, '-Sc',
       
   159            'import sys; print(repr(tuple(x for x in sys.version_info)))']
       
   160     _proc = subprocess.Popen(
       
   161         cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
       
   162     stdout, stderr = _proc.communicate();
       
   163     if _proc.returncode:
       
   164         raise RuntimeError(
       
   165             'error trying to get system packages:\n%s' % (stderr,))
       
   166     return eval(stdout.strip())
       
   167 
       
   168 
       
   169 class IncompatibleVersionError(zc.buildout.UserError):
       
   170     """A specified version is incompatible with a given requirement.
       
   171     """
       
   172 
       
   173 _versions = {sys.executable: '%d.%d' % sys.version_info[:2]}
       
   174 def _get_version(executable):
       
   175     try:
       
   176         return _versions[executable]
       
   177     except KeyError:
       
   178         cmd = _safe_arg(executable) + ' -V'
       
   179         p = subprocess.Popen(cmd,
       
   180                              shell=True,
       
   181                              stdin=subprocess.PIPE,
       
   182                              stdout=subprocess.PIPE,
       
   183                              stderr=subprocess.STDOUT,
       
   184                              close_fds=not is_win32)
       
   185         i, o = (p.stdin, p.stdout)
       
   186         i.close()
       
   187         version = o.read().strip()
       
   188         o.close()
       
   189         pystring, version = version.split()
       
   190         assert pystring == 'Python'
       
   191         version = re.match('(\d[.]\d)([.].*\d)?$', version).group(1)
       
   192         _versions[executable] = version
       
   193         return version
       
   194 
       
   195 FILE_SCHEME = re.compile('file://', re.I).match
       
   196 
       
   197 
       
   198 class AllowHostsPackageIndex(setuptools.package_index.PackageIndex):
       
   199     """Will allow urls that are local to the system.
       
   200 
       
   201     No matter what is allow_hosts.
       
   202     """
       
   203     def url_ok(self, url, fatal=False):
       
   204         if FILE_SCHEME(url):
       
   205             return True
       
   206         return setuptools.package_index.PackageIndex.url_ok(self, url, False)
       
   207 
       
   208 
       
   209 _indexes = {}
       
   210 def _get_index(executable, index_url, find_links, allow_hosts=('*',),
       
   211                path=None):
       
   212     # If path is None, the index will use sys.path.  If you provide an empty
       
   213     # path ([]), it will complain uselessly about missing index pages for
       
   214     # packages found in the paths that you expect to use.  Therefore, this path
       
   215     # is always the same as the _env path in the Installer.
       
   216     key = executable, index_url, tuple(find_links)
       
   217     index = _indexes.get(key)
       
   218     if index is not None:
       
   219         return index
       
   220 
       
   221     if index_url is None:
       
   222         index_url = default_index_url
       
   223     index = AllowHostsPackageIndex(
       
   224         index_url, hosts=allow_hosts, search_path=path,
       
   225         python=_get_version(executable)
       
   226         )
       
   227 
       
   228     if find_links:
       
   229         index.add_find_links(find_links)
       
   230 
       
   231     _indexes[key] = index
       
   232     return index
       
   233 
       
   234 clear_index_cache = _indexes.clear
       
   235 
       
   236 if is_win32:
       
   237     # work around spawn lamosity on windows
       
   238     # XXX need safe quoting (see the subprocess.list2cmdline) and test
       
   239     def _safe_arg(arg):
       
   240         return '"%s"' % arg
       
   241 else:
       
   242     _safe_arg = str
       
   243 
       
   244 # The following string is used to run easy_install in
       
   245 # Installer._call_easy_install.  It is usually started with python -S
       
   246 # (that is, don't import site at start).  That flag, and all of the code
       
   247 # in this snippet above the last two lines, exist to work around a
       
   248 # relatively rare problem.  If
       
   249 #
       
   250 # - your buildout configuration is trying to install a package that is within
       
   251 #   a namespace package, and
       
   252 #
       
   253 # - you use a Python that has a different version of this package
       
   254 #   installed in in its site-packages using
       
   255 #   --single-version-externally-managed (that is, using the mechanism
       
   256 #   sometimes used by system packagers:
       
   257 #   http://peak.telecommunity.com/DevCenter/setuptools#install-command ), and
       
   258 #
       
   259 # - the new package tries to do sys.path tricks in the setup.py to get a
       
   260 #   __version__,
       
   261 #
       
   262 # then the older package will be loaded first, making the setup version
       
   263 # the wrong number. While very arguably packages simply shouldn't do
       
   264 # the sys.path tricks, some do, and we don't want buildout to fall over
       
   265 # when they do.
       
   266 #
       
   267 # The namespace packages installed in site-packages with
       
   268 # --single-version-externally-managed use a mechanism that cause them to
       
   269 # be processed when site.py is imported  (see
       
   270 # http://mail.python.org/pipermail/distutils-sig/2009-May/011730.html
       
   271 # for another description of the problem).  Simply starting Python with
       
   272 # -S addresses the problem in Python 2.4 and 2.5, but Python 2.6's
       
   273 # distutils imports a value from the site module, so we unfortunately
       
   274 # have to do more drastic surgery in the _easy_install_preface code below.
       
   275 #
       
   276 # Here's an example of the .pth files created by setuptools when using that
       
   277 # flag:
       
   278 #
       
   279 # import sys,new,os;
       
   280 # p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('<NAMESPACE>',));
       
   281 # ie = os.path.exists(os.path.join(p,'__init__.py'));
       
   282 # m = not ie and sys.modules.setdefault('<NAMESPACE>',new.module('<NAMESPACE>'));
       
   283 # mp = (m or []) and m.__dict__.setdefault('__path__',[]);
       
   284 # (p not in mp) and mp.append(p)
       
   285 #
       
   286 # The code, below, then, runs under -S, indicating that site.py should
       
   287 # not be loaded initially.  It gets the initial sys.path under these
       
   288 # circumstances, and then imports site (because Python 2.6's distutils
       
   289 # will want it, as mentioned above). It then reinstates the old sys.path
       
   290 # value. Then it removes namespace packages (created by the setuptools
       
   291 # code above) from sys.modules.  It identifies namespace packages by
       
   292 # iterating over every loaded module.  It first looks if there is a
       
   293 # __path__, so it is a package; and then it sees if that __path__ does
       
   294 # not have an __init__.py.  (Note that PEP 382,
       
   295 # http://www.python.org/dev/peps/pep-0382, makes it possible to have a
       
   296 # namespace package that has an __init__.py, but also should make it
       
   297 # unnecessary for site.py to preprocess these packages, so it should be
       
   298 # fine, as far as can be guessed as of this writing.)  Finally, it
       
   299 # imports easy_install and runs it.
       
   300 _easy_install_preface = '''\
       
   301 import sys,os;\
       
   302 p = sys.path[:];\
       
   303 import site;\
       
   304 sys.path[:] = p;\
       
   305 [sys.modules.pop(k) for k, v in sys.modules.items()\
       
   306  if hasattr(v, '__path__') and len(v.__path__)==1 and\
       
   307  not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))];'''
       
   308 _easy_install_cmd = (
       
   309     'from setuptools.command.easy_install import main;main()')
       
   310 
       
   311 
       
   312 class Installer:
       
   313 
       
   314     _versions = {}
       
   315     _download_cache = None
       
   316     _install_from_cache = False
       
   317     _prefer_final = True
       
   318     _use_dependency_links = True
       
   319     _allow_picked_versions = True
       
   320     _always_unzip = False
       
   321     _include_site_packages = True
       
   322     _allowed_eggs_from_site_packages = ('*',)
       
   323 
       
   324     def __init__(self,
       
   325                  dest=None,
       
   326                  links=(),
       
   327                  index=None,
       
   328                  executable=sys.executable,
       
   329                  always_unzip=None,
       
   330                  path=None,
       
   331                  newest=True,
       
   332                  versions=None,
       
   333                  use_dependency_links=None,
       
   334                  allow_hosts=('*',),
       
   335                  include_site_packages=None,
       
   336                  allowed_eggs_from_site_packages=None,
       
   337                  prefer_final=None,
       
   338                  ):
       
   339         self._dest = dest
       
   340         self._allow_hosts = allow_hosts
       
   341 
       
   342         if self._install_from_cache:
       
   343             if not self._download_cache:
       
   344                 raise ValueError("install_from_cache set to true with no"
       
   345                                  " download cache")
       
   346             links = ()
       
   347             index = 'file://' + self._download_cache
       
   348 
       
   349         if use_dependency_links is not None:
       
   350             self._use_dependency_links = use_dependency_links
       
   351         if prefer_final is not None:
       
   352             self._prefer_final = prefer_final
       
   353         self._links = links = list(_fix_file_links(links))
       
   354         if self._download_cache and (self._download_cache not in links):
       
   355             links.insert(0, self._download_cache)
       
   356 
       
   357         self._index_url = index
       
   358         self._executable = executable
       
   359         self._has_broken_dash_S = _has_broken_dash_S(self._executable)
       
   360         if always_unzip is not None:
       
   361             self._always_unzip = always_unzip
       
   362         path = (path and path[:] or [])
       
   363         if include_site_packages is not None:
       
   364             self._include_site_packages = include_site_packages
       
   365         if allowed_eggs_from_site_packages is not None:
       
   366             self._allowed_eggs_from_site_packages = tuple(
       
   367                 allowed_eggs_from_site_packages)
       
   368         if self._has_broken_dash_S:
       
   369             if (not self._include_site_packages or
       
   370                 self._allowed_eggs_from_site_packages != ('*',)):
       
   371                 # We can't do this if the executable has a broken -S.
       
   372                 warnings.warn(BROKEN_DASH_S_WARNING)
       
   373                 self._include_site_packages = True
       
   374                 self._allowed_eggs_from_site_packages = ('*',)
       
   375             self._easy_install_cmd = _easy_install_cmd
       
   376         else:
       
   377             self._easy_install_cmd = _easy_install_preface + _easy_install_cmd
       
   378         self._easy_install_cmd = _safe_arg(self._easy_install_cmd)
       
   379         stdlib, self._site_packages = _get_system_paths(executable)
       
   380         version_info = _get_version_info(executable)
       
   381         if version_info == sys.version_info:
       
   382             # Maybe we can add the buildout and setuptools path.  If we
       
   383             # are including site_packages, we only have to include the extra
       
   384             # bits here, so we don't duplicate.  On the other hand, if we
       
   385             # are not including site_packages, we only want to include the
       
   386             # parts that are not in site_packages, so the code is the same.
       
   387             path.extend(
       
   388                 set(buildout_and_setuptools_path).difference(
       
   389                     self._site_packages))
       
   390         if self._include_site_packages:
       
   391             path.extend(self._site_packages)
       
   392         if dest is not None and dest not in path:
       
   393             path.insert(0, dest)
       
   394         self._path = path
       
   395         if self._dest is None:
       
   396             newest = False
       
   397         self._newest = newest
       
   398         self._env = pkg_resources.Environment(path,
       
   399                                               python=_get_version(executable))
       
   400         self._index = _get_index(executable, index, links, self._allow_hosts,
       
   401                                  self._path)
       
   402 
       
   403         if versions is not None:
       
   404             self._versions = versions
       
   405 
       
   406     _allowed_eggs_from_site_packages_regex = None
       
   407     def allow_site_package_egg(self, name):
       
   408         if (not self._include_site_packages or
       
   409             not self._allowed_eggs_from_site_packages):
       
   410             # If the answer is a blanket "no," perform a shortcut.
       
   411             return False
       
   412         if self._allowed_eggs_from_site_packages_regex is None:
       
   413             pattern = '(%s)' % (
       
   414                 '|'.join(
       
   415                     fnmatch.translate(name)
       
   416                     for name in self._allowed_eggs_from_site_packages),
       
   417                 )
       
   418             self._allowed_eggs_from_site_packages_regex = re.compile(pattern)
       
   419         return bool(self._allowed_eggs_from_site_packages_regex.match(name))
       
   420 
       
   421     def _satisfied(self, req, source=None):
       
   422         # We get all distributions that match the given requirement.  If we are
       
   423         # not supposed to include site-packages for the given egg, we also
       
   424         # filter those out. Even if include_site_packages is False and so we
       
   425         # have excluded site packages from the _env's paths (see
       
   426         # Installer.__init__), we need to do the filtering here because an
       
   427         # .egg-link, such as one for setuptools or zc.buildout installed by
       
   428         # zc.buildout.buildout.Buildout.bootstrap, can indirectly include a
       
   429         # path in our _site_packages.
       
   430         dists = [dist for dist in self._env[req.project_name] if (
       
   431                     dist in req and (
       
   432                         dist.location not in self._site_packages or
       
   433                         self.allow_site_package_egg(dist.project_name))
       
   434                     )
       
   435                 ]
       
   436         if not dists:
       
   437             logger.debug('We have no distributions for %s that satisfies %r.',
       
   438                          req.project_name, str(req))
       
   439 
       
   440             return None, self._obtain(req, source)
       
   441 
       
   442         # Note that dists are sorted from best to worst, as promised by
       
   443         # env.__getitem__
       
   444 
       
   445         for dist in dists:
       
   446             if (dist.precedence == pkg_resources.DEVELOP_DIST and
       
   447                 dist.location not in self._site_packages):
       
   448                 # System eggs are sometimes installed as develop eggs.
       
   449                 # Those are not the kind of develop eggs we are looking for
       
   450                 # here: we want ones that the buildout itself has locally as
       
   451                 # develop eggs.
       
   452                 logger.debug('We have a develop egg: %s', dist)
       
   453                 return dist, None
       
   454 
       
   455         # Special common case, we have a specification for a single version:
       
   456         specs = req.specs
       
   457         if len(specs) == 1 and specs[0][0] == '==':
       
   458             logger.debug('We have the distribution that satisfies %r.',
       
   459                          str(req))
       
   460             return dists[0], None
       
   461 
       
   462         if self._prefer_final:
       
   463             fdists = [dist for dist in dists
       
   464                       if _final_version(dist.parsed_version)
       
   465                       ]
       
   466             if fdists:
       
   467                 # There are final dists, so only use those
       
   468                 dists = fdists
       
   469 
       
   470         if not self._newest:
       
   471             # We don't need the newest, so we'll use the newest one we
       
   472             # find, which is the first returned by
       
   473             # Environment.__getitem__.
       
   474             return dists[0], None
       
   475 
       
   476         best_we_have = dists[0] # Because dists are sorted from best to worst
       
   477 
       
   478         # We have some installed distros.  There might, theoretically, be
       
   479         # newer ones.  Let's find out which ones are available and see if
       
   480         # any are newer.  We only do this if we're willing to install
       
   481         # something, which is only true if dest is not None:
       
   482 
       
   483         if self._dest is not None:
       
   484             best_available = self._obtain(req, source)
       
   485         else:
       
   486             best_available = None
       
   487 
       
   488         if best_available is None:
       
   489             # That's a bit odd.  There aren't any distros available.
       
   490             # We should use the best one we have that meets the requirement.
       
   491             logger.debug(
       
   492                 'There are no distros available that meet %r.\n'
       
   493                 'Using our best, %s.',
       
   494                 str(req), best_available)
       
   495             return best_we_have, None
       
   496 
       
   497         if self._prefer_final:
       
   498             if _final_version(best_available.parsed_version):
       
   499                 if _final_version(best_we_have.parsed_version):
       
   500                     if (best_we_have.parsed_version
       
   501                         <
       
   502                         best_available.parsed_version
       
   503                         ):
       
   504                         return None, best_available
       
   505                 else:
       
   506                     return None, best_available
       
   507             else:
       
   508                 if (not _final_version(best_we_have.parsed_version)
       
   509                     and
       
   510                     (best_we_have.parsed_version
       
   511                      <
       
   512                      best_available.parsed_version
       
   513                      )
       
   514                     ):
       
   515                     return None, best_available
       
   516         else:
       
   517             if (best_we_have.parsed_version
       
   518                 <
       
   519                 best_available.parsed_version
       
   520                 ):
       
   521                 return None, best_available
       
   522 
       
   523         logger.debug(
       
   524             'We have the best distribution that satisfies %r.',
       
   525             str(req))
       
   526         return best_we_have, None
       
   527 
       
   528     def _load_dist(self, dist):
       
   529         dists = pkg_resources.Environment(
       
   530             dist.location,
       
   531             python=_get_version(self._executable),
       
   532             )[dist.project_name]
       
   533         assert len(dists) == 1
       
   534         return dists[0]
       
   535 
       
   536     def _call_easy_install(self, spec, ws, dest, dist):
       
   537 
       
   538         tmp = tempfile.mkdtemp(dir=dest)
       
   539         try:
       
   540             path = setuptools_loc
       
   541 
       
   542             args = ('-c', self._easy_install_cmd, '-mUNxd', _safe_arg(tmp))
       
   543             if not self._has_broken_dash_S:
       
   544                 args = ('-S',) + args
       
   545             if self._always_unzip:
       
   546                 args += ('-Z', )
       
   547             level = logger.getEffectiveLevel()
       
   548             if level > 0:
       
   549                 args += ('-q', )
       
   550             elif level < 0:
       
   551                 args += ('-v', )
       
   552 
       
   553             args += (_safe_arg(spec), )
       
   554 
       
   555             if level <= logging.DEBUG:
       
   556                 logger.debug('Running easy_install:\n%s "%s"\npath=%s\n',
       
   557                              self._executable, '" "'.join(args), path)
       
   558 
       
   559             if is_jython:
       
   560                 extra_env = dict(os.environ, PYTHONPATH=path)
       
   561             else:
       
   562                 args += (dict(os.environ, PYTHONPATH=path), )
       
   563 
       
   564             sys.stdout.flush() # We want any pending output first
       
   565 
       
   566             if is_jython:
       
   567                 exit_code = subprocess.Popen(
       
   568                 [_safe_arg(self._executable)] + list(args),
       
   569                 env=extra_env).wait()
       
   570             else:
       
   571                 exit_code = os.spawnle(
       
   572                     os.P_WAIT, self._executable, _safe_arg (self._executable),
       
   573                     *args)
       
   574 
       
   575             dists = []
       
   576             env = pkg_resources.Environment(
       
   577                 [tmp],
       
   578                 python=_get_version(self._executable),
       
   579                 )
       
   580             for project in env:
       
   581                 dists.extend(env[project])
       
   582 
       
   583             if exit_code:
       
   584                 logger.error(
       
   585                     "An error occurred when trying to install %s. "
       
   586                     "Look above this message for any errors that "
       
   587                     "were output by easy_install.",
       
   588                     dist)
       
   589 
       
   590             if not dists:
       
   591                 raise zc.buildout.UserError("Couldn't install: %s" % dist)
       
   592 
       
   593             if len(dists) > 1:
       
   594                 logger.warn("Installing %s\n"
       
   595                             "caused multiple distributions to be installed:\n"
       
   596                             "%s\n",
       
   597                             dist, '\n'.join(map(str, dists)))
       
   598             else:
       
   599                 d = dists[0]
       
   600                 if d.project_name != dist.project_name:
       
   601                     logger.warn("Installing %s\n"
       
   602                                 "Caused installation of a distribution:\n"
       
   603                                 "%s\n"
       
   604                                 "with a different project name.",
       
   605                                 dist, d)
       
   606                 if d.version != dist.version:
       
   607                     logger.warn("Installing %s\n"
       
   608                                 "Caused installation of a distribution:\n"
       
   609                                 "%s\n"
       
   610                                 "with a different version.",
       
   611                                 dist, d)
       
   612 
       
   613             result = []
       
   614             for d in dists:
       
   615                 newloc = os.path.join(dest, os.path.basename(d.location))
       
   616                 if os.path.exists(newloc):
       
   617                     if os.path.isdir(newloc):
       
   618                         shutil.rmtree(newloc)
       
   619                     else:
       
   620                         os.remove(newloc)
       
   621                 os.rename(d.location, newloc)
       
   622 
       
   623                 [d] = pkg_resources.Environment(
       
   624                     [newloc],
       
   625                     python=_get_version(self._executable),
       
   626                     )[d.project_name]
       
   627 
       
   628                 result.append(d)
       
   629 
       
   630             return result
       
   631 
       
   632         finally:
       
   633             shutil.rmtree(tmp)
       
   634 
       
   635     def _obtain(self, requirement, source=None):
       
   636         # initialize out index for this project:
       
   637         index = self._index
       
   638 
       
   639         if index.obtain(requirement) is None:
       
   640             # Nothing is available.
       
   641             return None
       
   642 
       
   643         # Filter the available dists for the requirement and source flag.  If
       
   644         # we are not supposed to include site-packages for the given egg, we
       
   645         # also filter those out. Even if include_site_packages is False and so
       
   646         # we have excluded site packages from the _env's paths (see
       
   647         # Installer.__init__), we need to do the filtering here because an
       
   648         # .egg-link, such as one for setuptools or zc.buildout installed by
       
   649         # zc.buildout.buildout.Buildout.bootstrap, can indirectly include a
       
   650         # path in our _site_packages.
       
   651         dists = [dist for dist in index[requirement.project_name] if (
       
   652                     dist in requirement and (
       
   653                         dist.location not in self._site_packages or
       
   654                         self.allow_site_package_egg(dist.project_name))
       
   655                     and (
       
   656                         (not source) or
       
   657                         (dist.precedence == pkg_resources.SOURCE_DIST))
       
   658                     )
       
   659                  ]
       
   660 
       
   661         # If we prefer final dists, filter for final and use the
       
   662         # result if it is non empty.
       
   663         if self._prefer_final:
       
   664             fdists = [dist for dist in dists
       
   665                       if _final_version(dist.parsed_version)
       
   666                       ]
       
   667             if fdists:
       
   668                 # There are final dists, so only use those
       
   669                 dists = fdists
       
   670 
       
   671         # Now find the best one:
       
   672         best = []
       
   673         bestv = ()
       
   674         for dist in dists:
       
   675             distv = dist.parsed_version
       
   676             if distv > bestv:
       
   677                 best = [dist]
       
   678                 bestv = distv
       
   679             elif distv == bestv:
       
   680                 best.append(dist)
       
   681 
       
   682         if not best:
       
   683             return None
       
   684 
       
   685         if len(best) == 1:
       
   686             return best[0]
       
   687 
       
   688         if self._download_cache:
       
   689             for dist in best:
       
   690                 if (realpath(os.path.dirname(dist.location))
       
   691                     ==
       
   692                     self._download_cache
       
   693                     ):
       
   694                     return dist
       
   695 
       
   696         best.sort()
       
   697         return best[-1]
       
   698 
       
   699     def _fetch(self, dist, tmp, download_cache):
       
   700         if (download_cache
       
   701             and (realpath(os.path.dirname(dist.location)) == download_cache)
       
   702             ):
       
   703             return dist
       
   704 
       
   705         new_location = self._index.download(dist.location, tmp)
       
   706         if (download_cache
       
   707             and (realpath(new_location) == realpath(dist.location))
       
   708             and os.path.isfile(new_location)
       
   709             ):
       
   710             # setuptools avoids making extra copies, but we want to copy
       
   711             # to the download cache
       
   712             shutil.copy2(new_location, tmp)
       
   713             new_location = os.path.join(tmp, os.path.basename(new_location))
       
   714 
       
   715         return dist.clone(location=new_location)
       
   716 
       
   717     def _get_dist(self, requirement, ws, always_unzip):
       
   718 
       
   719         __doing__ = 'Getting distribution for %r.', str(requirement)
       
   720 
       
   721         # Maybe an existing dist is already the best dist that satisfies the
       
   722         # requirement
       
   723         dist, avail = self._satisfied(requirement)
       
   724 
       
   725         if dist is None:
       
   726             if self._dest is not None:
       
   727                 logger.info(*__doing__)
       
   728 
       
   729             # Retrieve the dist:
       
   730             if avail is None:
       
   731                 raise MissingDistribution(requirement, ws)
       
   732 
       
   733             # We may overwrite distributions, so clear importer
       
   734             # cache.
       
   735             sys.path_importer_cache.clear()
       
   736 
       
   737             tmp = self._download_cache
       
   738             if tmp is None:
       
   739                 tmp = tempfile.mkdtemp('get_dist')
       
   740 
       
   741             try:
       
   742                 dist = self._fetch(avail, tmp, self._download_cache)
       
   743 
       
   744                 if dist is None:
       
   745                     raise zc.buildout.UserError(
       
   746                         "Couldn't download distribution %s." % avail)
       
   747 
       
   748                 if dist.precedence == pkg_resources.EGG_DIST:
       
   749                     # It's already an egg, just fetch it into the dest
       
   750 
       
   751                     newloc = os.path.join(
       
   752                         self._dest, os.path.basename(dist.location))
       
   753 
       
   754                     if os.path.isdir(dist.location):
       
   755                         # we got a directory. It must have been
       
   756                         # obtained locally.  Just copy it.
       
   757                         shutil.copytree(dist.location, newloc)
       
   758                     else:
       
   759 
       
   760                         if self._always_unzip:
       
   761                             should_unzip = True
       
   762                         else:
       
   763                             metadata = pkg_resources.EggMetadata(
       
   764                                 zipimport.zipimporter(dist.location)
       
   765                                 )
       
   766                             should_unzip = (
       
   767                                 metadata.has_metadata('not-zip-safe')
       
   768                                 or
       
   769                                 not metadata.has_metadata('zip-safe')
       
   770                                 )
       
   771 
       
   772                         if should_unzip:
       
   773                             setuptools.archive_util.unpack_archive(
       
   774                                 dist.location, newloc)
       
   775                         else:
       
   776                             shutil.copyfile(dist.location, newloc)
       
   777 
       
   778                     redo_pyc(newloc)
       
   779 
       
   780                     # Getting the dist from the environment causes the
       
   781                     # distribution meta data to be read.  Cloning isn't
       
   782                     # good enough.
       
   783                     dists = pkg_resources.Environment(
       
   784                         [newloc],
       
   785                         python=_get_version(self._executable),
       
   786                         )[dist.project_name]
       
   787                 else:
       
   788                     # It's some other kind of dist.  We'll let easy_install
       
   789                     # deal with it:
       
   790                     dists = self._call_easy_install(
       
   791                         dist.location, ws, self._dest, dist)
       
   792                     for dist in dists:
       
   793                         redo_pyc(dist.location)
       
   794 
       
   795             finally:
       
   796                 if tmp != self._download_cache:
       
   797                     shutil.rmtree(tmp)
       
   798 
       
   799             self._env.scan([self._dest])
       
   800             dist = self._env.best_match(requirement, ws)
       
   801             logger.info("Got %s.", dist)
       
   802 
       
   803         else:
       
   804             dists = [dist]
       
   805 
       
   806         for dist in dists:
       
   807             if (dist.has_metadata('dependency_links.txt')
       
   808                 and not self._install_from_cache
       
   809                 and self._use_dependency_links
       
   810                 ):
       
   811                 for link in dist.get_metadata_lines('dependency_links.txt'):
       
   812                     link = link.strip()
       
   813                     if link not in self._links:
       
   814                         logger.debug('Adding find link %r from %s', link, dist)
       
   815                         self._links.append(link)
       
   816                         self._index = _get_index(self._executable,
       
   817                                                  self._index_url, self._links,
       
   818                                                  self._allow_hosts, self._path)
       
   819 
       
   820         for dist in dists:
       
   821             # Check whether we picked a version and, if we did, report it:
       
   822             if not (
       
   823                 dist.precedence == pkg_resources.DEVELOP_DIST
       
   824                 or
       
   825                 (len(requirement.specs) == 1
       
   826                  and
       
   827                  requirement.specs[0][0] == '==')
       
   828                 ):
       
   829                 logger.debug('Picked: %s = %s',
       
   830                              dist.project_name, dist.version)
       
   831                 if not self._allow_picked_versions:
       
   832                     raise zc.buildout.UserError(
       
   833                         'Picked: %s = %s' % (dist.project_name, dist.version)
       
   834                         )
       
   835 
       
   836         return dists
       
   837 
       
   838     def _maybe_add_setuptools(self, ws, dist):
       
   839         if dist.has_metadata('namespace_packages.txt'):
       
   840             for r in dist.requires():
       
   841                 if r.project_name in ('setuptools', 'distribute'):
       
   842                     break
       
   843             else:
       
   844                 # We have a namespace package but no requirement for setuptools
       
   845                 if dist.precedence == pkg_resources.DEVELOP_DIST:
       
   846                     logger.warn(
       
   847                         "Develop distribution: %s\n"
       
   848                         "uses namespace packages but the distribution "
       
   849                         "does not require setuptools.",
       
   850                         dist)
       
   851                 requirement = self._constrain(
       
   852                     pkg_resources.Requirement.parse('setuptools')
       
   853                     )
       
   854                 if ws.find(requirement) is None:
       
   855                     for dist in self._get_dist(requirement, ws, False):
       
   856                         ws.add(dist)
       
   857 
       
   858 
       
   859     def _constrain(self, requirement):
       
   860         if is_distribute and requirement.key == 'setuptools':
       
   861             requirement = pkg_resources.Requirement.parse('distribute')
       
   862         version = self._versions.get(requirement.project_name)
       
   863         if version:
       
   864             if version not in requirement:
       
   865                 logger.error("The version, %s, is not consistent with the "
       
   866                              "requirement, %r.", version, str(requirement))
       
   867                 raise IncompatibleVersionError("Bad version", version)
       
   868 
       
   869             requirement = pkg_resources.Requirement.parse(
       
   870                 "%s[%s] ==%s" % (requirement.project_name,
       
   871                                ','.join(requirement.extras),
       
   872                                version))
       
   873 
       
   874         return requirement
       
   875 
       
   876     def install(self, specs, working_set=None):
       
   877 
       
   878         logger.debug('Installing %s.', repr(specs)[1:-1])
       
   879 
       
   880         path = self._path
       
   881         destination = self._dest
       
   882         if destination is not None and destination not in path:
       
   883             path.insert(0, destination)
       
   884 
       
   885         requirements = [self._constrain(pkg_resources.Requirement.parse(spec))
       
   886                         for spec in specs]
       
   887 
       
   888 
       
   889 
       
   890         if working_set is None:
       
   891             ws = pkg_resources.WorkingSet([])
       
   892         else:
       
   893             ws = working_set
       
   894 
       
   895         for requirement in requirements:
       
   896             for dist in self._get_dist(requirement, ws, self._always_unzip):
       
   897                 ws.add(dist)
       
   898                 self._maybe_add_setuptools(ws, dist)
       
   899 
       
   900         # OK, we have the requested distributions and they're in the working
       
   901         # set, but they may have unmet requirements.  We'll resolve these
       
   902         # requirements. This is code modified from
       
   903         # pkg_resources.WorkingSet.resolve.  We can't reuse that code directly
       
   904         # because we have to constrain our requirements (see
       
   905         # versions_section_ignored_for_dependency_in_favor_of_site_packages in
       
   906         # zc.buildout.tests).
       
   907         requirements.reverse() # Set up the stack.
       
   908         processed = {}  # This is a set of processed requirements.
       
   909         best = {}  # This is a mapping of key -> dist.
       
   910         # Note that we don't use the existing environment, because we want
       
   911         # to look for new eggs unless what we have is the best that
       
   912         # matches the requirement.
       
   913         env = pkg_resources.Environment(ws.entries)
       
   914         while requirements:
       
   915             # Process dependencies breadth-first.
       
   916             req = self._constrain(requirements.pop(0))
       
   917             if req in processed:
       
   918                 # Ignore cyclic or redundant dependencies.
       
   919                 continue
       
   920             dist = best.get(req.key)
       
   921             if dist is None:
       
   922                 # Find the best distribution and add it to the map.
       
   923                 dist = ws.by_key.get(req.key)
       
   924                 if dist is None:
       
   925                     try:
       
   926                         dist = best[req.key] = env.best_match(req, ws)
       
   927                     except pkg_resources.VersionConflict, err:
       
   928                         raise VersionConflict(err, ws)
       
   929                     if dist is None or (
       
   930                         dist.location in self._site_packages and not
       
   931                         self.allow_site_package_egg(dist.project_name)):
       
   932                         # If we didn't find a distribution in the
       
   933                         # environment, or what we found is from site
       
   934                         # packages and not allowed to be there, try
       
   935                         # again.
       
   936                         if destination:
       
   937                             logger.debug('Getting required %r', str(req))
       
   938                         else:
       
   939                             logger.debug('Adding required %r', str(req))
       
   940                         _log_requirement(ws, req)
       
   941                         for dist in self._get_dist(req,
       
   942                                                    ws, self._always_unzip):
       
   943                             ws.add(dist)
       
   944                             self._maybe_add_setuptools(ws, dist)
       
   945             if dist not in req:
       
   946                 # Oops, the "best" so far conflicts with a dependency.
       
   947                 raise VersionConflict(
       
   948                     pkg_resources.VersionConflict(dist, req), ws)
       
   949             requirements.extend(dist.requires(req.extras)[::-1])
       
   950             processed[req] = True
       
   951             if dist.location in self._site_packages:
       
   952                 logger.debug('Egg from site-packages: %s', dist)
       
   953         return ws
       
   954 
       
   955     def build(self, spec, build_ext):
       
   956 
       
   957         requirement = self._constrain(pkg_resources.Requirement.parse(spec))
       
   958 
       
   959         dist, avail = self._satisfied(requirement, 1)
       
   960         if dist is not None:
       
   961             return [dist.location]
       
   962 
       
   963         # Retrieve the dist:
       
   964         if avail is None:
       
   965             raise zc.buildout.UserError(
       
   966                 "Couldn't find a source distribution for %r."
       
   967                 % str(requirement))
       
   968 
       
   969         logger.debug('Building %r', spec)
       
   970 
       
   971         tmp = self._download_cache
       
   972         if tmp is None:
       
   973             tmp = tempfile.mkdtemp('get_dist')
       
   974 
       
   975         try:
       
   976             dist = self._fetch(avail, tmp, self._download_cache)
       
   977 
       
   978             build_tmp = tempfile.mkdtemp('build')
       
   979             try:
       
   980                 setuptools.archive_util.unpack_archive(dist.location,
       
   981                                                        build_tmp)
       
   982                 if os.path.exists(os.path.join(build_tmp, 'setup.py')):
       
   983                     base = build_tmp
       
   984                 else:
       
   985                     setups = glob.glob(
       
   986                         os.path.join(build_tmp, '*', 'setup.py'))
       
   987                     if not setups:
       
   988                         raise distutils.errors.DistutilsError(
       
   989                             "Couldn't find a setup script in %s"
       
   990                             % os.path.basename(dist.location)
       
   991                             )
       
   992                     if len(setups) > 1:
       
   993                         raise distutils.errors.DistutilsError(
       
   994                             "Multiple setup scripts in %s"
       
   995                             % os.path.basename(dist.location)
       
   996                             )
       
   997                     base = os.path.dirname(setups[0])
       
   998 
       
   999                 setup_cfg = os.path.join(base, 'setup.cfg')
       
  1000                 if not os.path.exists(setup_cfg):
       
  1001                     f = open(setup_cfg, 'w')
       
  1002                     f.close()
       
  1003                 setuptools.command.setopt.edit_config(
       
  1004                     setup_cfg, dict(build_ext=build_ext))
       
  1005 
       
  1006                 dists = self._call_easy_install(
       
  1007                     base, pkg_resources.WorkingSet(),
       
  1008                     self._dest, dist)
       
  1009 
       
  1010                 for dist in dists:
       
  1011                     redo_pyc(dist.location)
       
  1012 
       
  1013                 return [dist.location for dist in dists]
       
  1014             finally:
       
  1015                 shutil.rmtree(build_tmp)
       
  1016 
       
  1017         finally:
       
  1018             if tmp != self._download_cache:
       
  1019                 shutil.rmtree(tmp)
       
  1020 
       
  1021 def default_versions(versions=None):
       
  1022     old = Installer._versions
       
  1023     if versions is not None:
       
  1024         Installer._versions = versions
       
  1025     return old
       
  1026 
       
  1027 def download_cache(path=-1):
       
  1028     old = Installer._download_cache
       
  1029     if path != -1:
       
  1030         if path:
       
  1031             path = realpath(path)
       
  1032         Installer._download_cache = path
       
  1033     return old
       
  1034 
       
  1035 def install_from_cache(setting=None):
       
  1036     old = Installer._install_from_cache
       
  1037     if setting is not None:
       
  1038         Installer._install_from_cache = bool(setting)
       
  1039     return old
       
  1040 
       
  1041 def prefer_final(setting=None):
       
  1042     old = Installer._prefer_final
       
  1043     if setting is not None:
       
  1044         Installer._prefer_final = bool(setting)
       
  1045     return old
       
  1046 
       
  1047 def include_site_packages(setting=None):
       
  1048     old = Installer._include_site_packages
       
  1049     if setting is not None:
       
  1050         Installer._include_site_packages = bool(setting)
       
  1051     return old
       
  1052 
       
  1053 def allowed_eggs_from_site_packages(setting=None):
       
  1054     old = Installer._allowed_eggs_from_site_packages
       
  1055     if setting is not None:
       
  1056         Installer._allowed_eggs_from_site_packages = tuple(setting)
       
  1057     return old
       
  1058 
       
  1059 def use_dependency_links(setting=None):
       
  1060     old = Installer._use_dependency_links
       
  1061     if setting is not None:
       
  1062         Installer._use_dependency_links = bool(setting)
       
  1063     return old
       
  1064 
       
  1065 def allow_picked_versions(setting=None):
       
  1066     old = Installer._allow_picked_versions
       
  1067     if setting is not None:
       
  1068         Installer._allow_picked_versions = bool(setting)
       
  1069     return old
       
  1070 
       
  1071 def always_unzip(setting=None):
       
  1072     old = Installer._always_unzip
       
  1073     if setting is not None:
       
  1074         Installer._always_unzip = bool(setting)
       
  1075     return old
       
  1076 
       
  1077 def install(specs, dest,
       
  1078             links=(), index=None,
       
  1079             executable=sys.executable, always_unzip=None,
       
  1080             path=None, working_set=None, newest=True, versions=None,
       
  1081             use_dependency_links=None, allow_hosts=('*',),
       
  1082             include_site_packages=None, allowed_eggs_from_site_packages=None,
       
  1083             prefer_final=None):
       
  1084     installer = Installer(
       
  1085         dest, links, index, executable, always_unzip, path, newest,
       
  1086         versions, use_dependency_links, allow_hosts=allow_hosts,
       
  1087         include_site_packages=include_site_packages,
       
  1088         allowed_eggs_from_site_packages=allowed_eggs_from_site_packages,
       
  1089         prefer_final=prefer_final)
       
  1090     return installer.install(specs, working_set)
       
  1091 
       
  1092 
       
  1093 def build(spec, dest, build_ext,
       
  1094           links=(), index=None,
       
  1095           executable=sys.executable,
       
  1096           path=None, newest=True, versions=None, allow_hosts=('*',),
       
  1097           include_site_packages=None, allowed_eggs_from_site_packages=None):
       
  1098     installer = Installer(
       
  1099         dest, links, index, executable, True, path, newest, versions,
       
  1100         allow_hosts=allow_hosts,
       
  1101         include_site_packages=include_site_packages,
       
  1102         allowed_eggs_from_site_packages=allowed_eggs_from_site_packages)
       
  1103     return installer.build(spec, build_ext)
       
  1104 
       
  1105 
       
  1106 
       
  1107 def _rm(*paths):
       
  1108     for path in paths:
       
  1109         if os.path.isdir(path):
       
  1110             shutil.rmtree(path)
       
  1111         elif os.path.exists(path):
       
  1112             os.remove(path)
       
  1113 
       
  1114 def _copyeggs(src, dest, suffix, undo):
       
  1115     result = []
       
  1116     undo.append(lambda : _rm(*result))
       
  1117     for name in os.listdir(src):
       
  1118         if name.endswith(suffix):
       
  1119             new = os.path.join(dest, name)
       
  1120             _rm(new)
       
  1121             os.rename(os.path.join(src, name), new)
       
  1122             result.append(new)
       
  1123 
       
  1124     assert len(result) == 1, str(result)
       
  1125     undo.pop()
       
  1126 
       
  1127     return result[0]
       
  1128 
       
  1129 def develop(setup, dest,
       
  1130             build_ext=None,
       
  1131             executable=sys.executable):
       
  1132 
       
  1133     if os.path.isdir(setup):
       
  1134         directory = setup
       
  1135         setup = os.path.join(directory, 'setup.py')
       
  1136     else:
       
  1137         directory = os.path.dirname(setup)
       
  1138 
       
  1139     undo = []
       
  1140     try:
       
  1141         if build_ext:
       
  1142             setup_cfg = os.path.join(directory, 'setup.cfg')
       
  1143             if os.path.exists(setup_cfg):
       
  1144                 os.rename(setup_cfg, setup_cfg+'-develop-aside')
       
  1145                 def restore_old_setup():
       
  1146                     if os.path.exists(setup_cfg):
       
  1147                         os.remove(setup_cfg)
       
  1148                     os.rename(setup_cfg+'-develop-aside', setup_cfg)
       
  1149                 undo.append(restore_old_setup)
       
  1150             else:
       
  1151                 open(setup_cfg, 'w')
       
  1152                 undo.append(lambda: os.remove(setup_cfg))
       
  1153             setuptools.command.setopt.edit_config(
       
  1154                 setup_cfg, dict(build_ext=build_ext))
       
  1155 
       
  1156         fd, tsetup = tempfile.mkstemp()
       
  1157         undo.append(lambda: os.remove(tsetup))
       
  1158         undo.append(lambda: os.close(fd))
       
  1159 
       
  1160         os.write(fd, runsetup_template % dict(
       
  1161             setuptools=setuptools_loc,
       
  1162             setupdir=directory,
       
  1163             setup=setup,
       
  1164             __file__ = setup,
       
  1165             ))
       
  1166 
       
  1167         tmp3 = tempfile.mkdtemp('build', dir=dest)
       
  1168         undo.append(lambda : shutil.rmtree(tmp3))
       
  1169 
       
  1170         args = [
       
  1171             zc.buildout.easy_install._safe_arg(tsetup),
       
  1172             '-q', 'develop', '-mxN',
       
  1173             '-d', _safe_arg(tmp3),
       
  1174             ]
       
  1175 
       
  1176         log_level = logger.getEffectiveLevel()
       
  1177         if log_level <= 0:
       
  1178             if log_level == 0:
       
  1179                 del args[1]
       
  1180             else:
       
  1181                 args[1] == '-v'
       
  1182         if log_level < logging.DEBUG:
       
  1183             logger.debug("in: %r\n%s", directory, ' '.join(args))
       
  1184 
       
  1185         if is_jython:
       
  1186             assert subprocess.Popen([_safe_arg(executable)] + args).wait() == 0
       
  1187         else:
       
  1188             assert os.spawnl(os.P_WAIT, executable, _safe_arg(executable),
       
  1189                              *args) == 0
       
  1190 
       
  1191         return _copyeggs(tmp3, dest, '.egg-link', undo)
       
  1192 
       
  1193     finally:
       
  1194         undo.reverse()
       
  1195         [f() for f in undo]
       
  1196 
       
  1197 def working_set(specs, executable, path, include_site_packages=None,
       
  1198                 allowed_eggs_from_site_packages=None, prefer_final=None):
       
  1199     return install(
       
  1200         specs, None, executable=executable, path=path,
       
  1201         include_site_packages=include_site_packages,
       
  1202         allowed_eggs_from_site_packages=allowed_eggs_from_site_packages,
       
  1203         prefer_final=prefer_final)
       
  1204 
       
  1205 ############################################################################
       
  1206 # Script generation functions
       
  1207 
       
  1208 def scripts(
       
  1209     reqs, working_set, executable, dest,
       
  1210     scripts=None,
       
  1211     extra_paths=(),
       
  1212     arguments='',
       
  1213     interpreter=None,
       
  1214     initialization='',
       
  1215     relative_paths=False,
       
  1216     ):
       
  1217     """Generate scripts and/or an interpreter.
       
  1218 
       
  1219     See sitepackage_safe_scripts for a version that can be used with a Python
       
  1220     that has code installed in site-packages. It has more options and a
       
  1221     different approach.
       
  1222     """
       
  1223     path = _get_path(working_set, extra_paths)
       
  1224     if initialization:
       
  1225         initialization = '\n'+initialization+'\n'
       
  1226     generated = _generate_scripts(
       
  1227         reqs, working_set, dest, path, scripts, relative_paths,
       
  1228         initialization, executable, arguments)
       
  1229     if interpreter:
       
  1230         sname = os.path.join(dest, interpreter)
       
  1231         spath, rpsetup = _relative_path_and_setup(sname, path, relative_paths)
       
  1232         generated.extend(
       
  1233             _pyscript(spath, sname, executable, rpsetup))
       
  1234     return generated
       
  1235 
       
  1236 # We need to give an alternate name to the ``scripts`` function so that it
       
  1237 # can be referenced within sitepackage_safe_scripts, which uses ``scripts``
       
  1238 # as an argument name.
       
  1239 _original_scripts_function = scripts
       
  1240 
       
  1241 def sitepackage_safe_scripts(
       
  1242     dest, working_set, executable, site_py_dest,
       
  1243     reqs=(),
       
  1244     scripts=None,
       
  1245     interpreter=None,
       
  1246     extra_paths=(),
       
  1247     initialization='',
       
  1248     include_site_packages=False,
       
  1249     exec_sitecustomize=False,
       
  1250     relative_paths=False,
       
  1251     script_arguments='',
       
  1252     script_initialization='',
       
  1253     ):
       
  1254     """Generate scripts and/or an interpreter from a system Python.
       
  1255 
       
  1256     This accomplishes the same job as the ``scripts`` function, above,
       
  1257     but it does so in an alternative way that allows safely including
       
  1258     Python site packages, if desired, and  choosing to execute the Python's
       
  1259     sitecustomize.
       
  1260     """
       
  1261     if _has_broken_dash_S(executable):
       
  1262         if not include_site_packages:
       
  1263             warnings.warn(BROKEN_DASH_S_WARNING)
       
  1264         return _original_scripts_function(
       
  1265             reqs, working_set, executable, dest, scripts, extra_paths,
       
  1266             script_arguments, interpreter, initialization, relative_paths)
       
  1267     generated = []
       
  1268     generated.append(_generate_sitecustomize(
       
  1269         site_py_dest, executable, initialization, exec_sitecustomize))
       
  1270     generated.append(_generate_site(
       
  1271         site_py_dest, working_set, executable, extra_paths,
       
  1272         include_site_packages, relative_paths))
       
  1273     script_initialization = _script_initialization_template % dict(
       
  1274         site_py_dest=site_py_dest,
       
  1275         script_initialization=script_initialization)
       
  1276     if not script_initialization.endswith('\n'):
       
  1277         script_initialization += '\n'
       
  1278     generated.extend(_generate_scripts(
       
  1279         reqs, working_set, dest, [site_py_dest], scripts, relative_paths,
       
  1280         script_initialization, executable, script_arguments, block_site=True))
       
  1281     if interpreter:
       
  1282         generated.extend(_generate_interpreter(
       
  1283             interpreter, dest, executable, site_py_dest, relative_paths))
       
  1284     return generated
       
  1285 
       
  1286 _script_initialization_template = '''
       
  1287 import os
       
  1288 path = sys.path[0]
       
  1289 if os.environ.get('PYTHONPATH'):
       
  1290     path = os.pathsep.join([path, os.environ['PYTHONPATH']])
       
  1291 os.environ['BUILDOUT_ORIGINAL_PYTHONPATH'] = os.environ.get('PYTHONPATH', '')
       
  1292 os.environ['PYTHONPATH'] = path
       
  1293 import site # imports custom buildout-generated site.py
       
  1294 %(script_initialization)s'''
       
  1295 
       
  1296 # Utilities for the script generation functions.
       
  1297 
       
  1298 # These are shared by both ``scripts`` and ``sitepackage_safe_scripts``
       
  1299 
       
  1300 def _get_path(working_set, extra_paths=()):
       
  1301     """Given working set and extra paths, return a normalized path list."""
       
  1302     path = [dist.location for dist in working_set]
       
  1303     path.extend(extra_paths)
       
  1304     return map(realpath, path)
       
  1305 
       
  1306 def _generate_scripts(reqs, working_set, dest, path, scripts, relative_paths,
       
  1307                       initialization, executable, arguments,
       
  1308                       block_site=False):
       
  1309     """Generate scripts for the given requirements.
       
  1310 
       
  1311     - reqs is an iterable of string requirements or entry points.
       
  1312     - The requirements must be findable in the given working_set.
       
  1313     - The dest is the directory in which the scripts should be created.
       
  1314     - The path is a list of paths that should be added to sys.path.
       
  1315     - The scripts is an optional dictionary.  If included, the keys should be
       
  1316       the names of the scripts that should be created, as identified in their
       
  1317       entry points; and the values should be the name the script should
       
  1318       actually be created with.
       
  1319     - relative_paths, if given, should be the path that is the root of the
       
  1320       buildout (the common path that should be the root of what is relative).
       
  1321     """
       
  1322     if isinstance(reqs, str):
       
  1323         raise TypeError('Expected iterable of requirements or entry points,'
       
  1324                         ' got string.')
       
  1325     generated = []
       
  1326     entry_points = []
       
  1327     for req in reqs:
       
  1328         if isinstance(req, str):
       
  1329             req = pkg_resources.Requirement.parse(req)
       
  1330             dist = working_set.find(req)
       
  1331             for name in pkg_resources.get_entry_map(dist, 'console_scripts'):
       
  1332                 entry_point = dist.get_entry_info('console_scripts', name)
       
  1333                 entry_points.append(
       
  1334                     (name, entry_point.module_name,
       
  1335                      '.'.join(entry_point.attrs))
       
  1336                     )
       
  1337         else:
       
  1338             entry_points.append(req)
       
  1339     for name, module_name, attrs in entry_points:
       
  1340         if scripts is not None:
       
  1341             sname = scripts.get(name)
       
  1342             if sname is None:
       
  1343                 continue
       
  1344         else:
       
  1345             sname = name
       
  1346         sname = os.path.join(dest, sname)
       
  1347         spath, rpsetup = _relative_path_and_setup(sname, path, relative_paths)
       
  1348         generated.extend(
       
  1349             _script(sname, executable, rpsetup, spath, initialization,
       
  1350                     module_name, attrs, arguments, block_site=block_site))
       
  1351     return generated
       
  1352 
       
  1353 def _relative_path_and_setup(sname, path,
       
  1354                              relative_paths=False, indent_level=1,
       
  1355                              omit_os_import=False):
       
  1356     """Return a string of code of paths and of setup if appropriate.
       
  1357 
       
  1358     - sname is the full path to the script name to be created.
       
  1359     - path is the list of paths to be added to sys.path.
       
  1360     - relative_paths, if given, should be the path that is the root of the
       
  1361       buildout (the common path that should be the root of what is relative).
       
  1362     - indent_level is the number of four-space indents that the path should
       
  1363       insert before each element of the path.
       
  1364     """
       
  1365     if relative_paths:
       
  1366         relative_paths = os.path.normcase(relative_paths)
       
  1367         sname = os.path.normcase(os.path.abspath(sname))
       
  1368         spath = _format_paths(
       
  1369             [_relativitize(os.path.normcase(path_item), sname, relative_paths)
       
  1370              for path_item in path], indent_level=indent_level)
       
  1371         rpsetup = relative_paths_setup
       
  1372         if not omit_os_import:
       
  1373             rpsetup = '\n\nimport os\n' + rpsetup
       
  1374         for i in range(_relative_depth(relative_paths, sname)):
       
  1375             rpsetup += "\nbase = os.path.dirname(base)"
       
  1376     else:
       
  1377         spath = _format_paths((repr(p) for p in path),
       
  1378                               indent_level=indent_level)
       
  1379         rpsetup = ''
       
  1380     return spath, rpsetup
       
  1381 
       
  1382 def _relative_depth(common, path):
       
  1383     """Return number of dirs separating ``path`` from ancestor, ``common``.
       
  1384 
       
  1385     For instance, if path is /foo/bar/baz/bing, and common is /foo, this will
       
  1386     return 2--in UNIX, the number of ".." to get from bing's directory
       
  1387     to foo.
       
  1388 
       
  1389     This is a helper for _relative_path_and_setup.
       
  1390     """
       
  1391     n = 0
       
  1392     while 1:
       
  1393         dirname = os.path.dirname(path)
       
  1394         if dirname == path:
       
  1395             raise AssertionError("dirname of %s is the same" % dirname)
       
  1396         if dirname == common:
       
  1397             break
       
  1398         n += 1
       
  1399         path = dirname
       
  1400     return n
       
  1401 
       
  1402 def _relative_path(common, path):
       
  1403     """Return the relative path from ``common`` to ``path``.
       
  1404 
       
  1405     This is a helper for _relativitize, which is a helper to
       
  1406     _relative_path_and_setup.
       
  1407     """
       
  1408     r = []
       
  1409     while 1:
       
  1410         dirname, basename = os.path.split(path)
       
  1411         r.append(basename)
       
  1412         if dirname == common:
       
  1413             break
       
  1414         if dirname == path:
       
  1415             raise AssertionError("dirname of %s is the same" % dirname)
       
  1416         path = dirname
       
  1417     r.reverse()
       
  1418     return os.path.join(*r)
       
  1419 
       
  1420 def _relativitize(path, script, relative_paths):
       
  1421     """Return a code string for the given path.
       
  1422 
       
  1423     Path is relative to the base path ``relative_paths``if the common prefix
       
  1424     between ``path`` and ``script`` starts with ``relative_paths``.
       
  1425     """
       
  1426     if path == script:
       
  1427         raise AssertionError("path == script")
       
  1428     common = os.path.dirname(os.path.commonprefix([path, script]))
       
  1429     if (common == relative_paths or
       
  1430         common.startswith(os.path.join(relative_paths, ''))
       
  1431         ):
       
  1432         return "join(base, %r)" % _relative_path(common, path)
       
  1433     else:
       
  1434         return repr(path)
       
  1435 
       
  1436 relative_paths_setup = """
       
  1437 join = os.path.join
       
  1438 base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))"""
       
  1439 
       
  1440 def _write_script(full_name, contents, logged_type):
       
  1441     """Write contents of script in full_name, logging the action.
       
  1442 
       
  1443     The only tricky bit in this function is that it supports Windows by
       
  1444     creating exe files using a pkg_resources helper.
       
  1445     """
       
  1446     generated = []
       
  1447     script_name = full_name
       
  1448     if is_win32:
       
  1449         script_name += '-script.py'
       
  1450         # Generate exe file and give the script a magic name.
       
  1451         exe = full_name + '.exe'
       
  1452         new_data = pkg_resources.resource_string('setuptools', 'cli.exe')
       
  1453         if not os.path.exists(exe) or (open(exe, 'rb').read() != new_data):
       
  1454             # Only write it if it's different.
       
  1455             open(exe, 'wb').write(new_data)
       
  1456         generated.append(exe)
       
  1457     changed = not (os.path.exists(script_name) and
       
  1458                    open(script_name).read() == contents)
       
  1459     if changed:
       
  1460         open(script_name, 'w').write(contents)
       
  1461         try:
       
  1462             os.chmod(script_name, 0755)
       
  1463         except (AttributeError, os.error):
       
  1464             pass
       
  1465         logger.info("Generated %s %r.", logged_type, full_name)
       
  1466     generated.append(script_name)
       
  1467     return generated
       
  1468 
       
  1469 def _format_paths(paths, indent_level=1):
       
  1470     """Format paths for inclusion in a script."""
       
  1471     separator = ',\n' + indent_level * '    '
       
  1472     return separator.join(paths)
       
  1473 
       
  1474 def _script(dest, executable, relative_paths_setup, path, initialization,
       
  1475             module_name, attrs, arguments, block_site=False):
       
  1476     if block_site:
       
  1477         dash_S = ' -S'
       
  1478     else:
       
  1479         dash_S = ''
       
  1480     contents = script_template % dict(
       
  1481         python=_safe_arg(executable),
       
  1482         dash_S=dash_S,
       
  1483         path=path,
       
  1484         module_name=module_name,
       
  1485         attrs=attrs,
       
  1486         arguments=arguments,
       
  1487         initialization=initialization,
       
  1488         relative_paths_setup=relative_paths_setup,
       
  1489         )
       
  1490     return _write_script(dest, contents, 'script')
       
  1491 
       
  1492 if is_jython and jython_os_name == 'linux':
       
  1493     script_header = '#!/usr/bin/env %(python)s%(dash_S)s'
       
  1494 else:
       
  1495     script_header = '#!%(python)s%(dash_S)s'
       
  1496 
       
  1497 sys_path_template = '''\
       
  1498 import sys
       
  1499 sys.path[0:0] = [
       
  1500     %s,
       
  1501     ]
       
  1502 '''
       
  1503 
       
  1504 script_template = script_header + '''\
       
  1505 %(relative_paths_setup)s
       
  1506 
       
  1507 import sys
       
  1508 sys.path[0:0] = [
       
  1509     %(path)s,
       
  1510     ]
       
  1511 
       
  1512 %(initialization)s
       
  1513 import %(module_name)s
       
  1514 
       
  1515 if __name__ == '__main__':
       
  1516     %(module_name)s.%(attrs)s(%(arguments)s)
       
  1517 '''
       
  1518 
       
  1519 # These are used only by the older ``scripts`` function.
       
  1520 
       
  1521 def _pyscript(path, dest, executable, rsetup):
       
  1522     contents = py_script_template % dict(
       
  1523         python=_safe_arg(executable),
       
  1524         dash_S='',
       
  1525         path=path,
       
  1526         relative_paths_setup=rsetup,
       
  1527         )
       
  1528     return _write_script(dest, contents, 'interpreter')
       
  1529 
       
  1530 py_script_template = script_header + '''\
       
  1531 %(relative_paths_setup)s
       
  1532 
       
  1533 import sys
       
  1534 
       
  1535 sys.path[0:0] = [
       
  1536     %(path)s,
       
  1537     ]
       
  1538 
       
  1539 _interactive = True
       
  1540 if len(sys.argv) > 1:
       
  1541     _options, _args = __import__("getopt").getopt(sys.argv[1:], 'ic:m:')
       
  1542     _interactive = False
       
  1543     for (_opt, _val) in _options:
       
  1544         if _opt == '-i':
       
  1545             _interactive = True
       
  1546         elif _opt == '-c':
       
  1547             exec _val
       
  1548         elif _opt == '-m':
       
  1549             sys.argv[1:] = _args
       
  1550             _args = []
       
  1551             __import__("runpy").run_module(
       
  1552                  _val, {}, "__main__", alter_sys=True)
       
  1553 
       
  1554     if _args:
       
  1555         sys.argv[:] = _args
       
  1556         __file__ = _args[0]
       
  1557         del _options, _args
       
  1558         execfile(__file__)
       
  1559 
       
  1560 if _interactive:
       
  1561     del _interactive
       
  1562     __import__("code").interact(banner="", local=globals())
       
  1563 '''
       
  1564 
       
  1565 # These are used only by the newer ``sitepackage_safe_scripts`` function.
       
  1566 
       
  1567 def _get_module_file(executable, name, silent=False):
       
  1568     """Return a module's file path.
       
  1569 
       
  1570     - executable is a path to the desired Python executable.
       
  1571     - name is the name of the (pure, not C) Python module.
       
  1572     """
       
  1573     cmd = [executable, "-Sc",
       
  1574            "import imp; "
       
  1575            "fp, path, desc = imp.find_module(%r); "
       
  1576            "fp.close(); "
       
  1577            "print path" % (name,)]
       
  1578     env = os.environ.copy()
       
  1579     # We need to make sure that PYTHONPATH, which will often be set to
       
  1580     # include a custom buildout-generated site.py, is not set, or else
       
  1581     # we will not get an accurate value for the "real" site.py and
       
  1582     # sitecustomize.py.
       
  1583     env.pop('PYTHONPATH', None)
       
  1584     _proc = subprocess.Popen(
       
  1585         cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
       
  1586     stdout, stderr = _proc.communicate();
       
  1587     if _proc.returncode:
       
  1588         if not silent:
       
  1589             logger.info(
       
  1590                 'Could not find file for module %s:\n%s', name, stderr)
       
  1591         return None
       
  1592     # else: ...
       
  1593     res = stdout.strip()
       
  1594     if res.endswith('.pyc') or res.endswith('.pyo'):
       
  1595         raise RuntimeError('Cannot find uncompiled version of %s' % (name,))
       
  1596     if not os.path.exists(res):
       
  1597         raise RuntimeError(
       
  1598             'File does not exist for module %s:\n%s' % (name, res))
       
  1599     return res
       
  1600 
       
  1601 def _generate_sitecustomize(dest, executable, initialization='',
       
  1602                             exec_sitecustomize=False):
       
  1603     """Write a sitecustomize file with optional custom initialization.
       
  1604 
       
  1605     The created script will execute the underlying Python's
       
  1606     sitecustomize if exec_sitecustomize is True.
       
  1607     """
       
  1608     sitecustomize_path = os.path.join(dest, 'sitecustomize.py')
       
  1609     sitecustomize = open(sitecustomize_path, 'w')
       
  1610     if initialization:
       
  1611         sitecustomize.write(initialization + '\n')
       
  1612     if exec_sitecustomize:
       
  1613         real_sitecustomize_path = _get_module_file(
       
  1614             executable, 'sitecustomize', silent=True)
       
  1615         if real_sitecustomize_path:
       
  1616             real_sitecustomize = open(real_sitecustomize_path, 'r')
       
  1617             sitecustomize.write(
       
  1618                 '\n# The following is from\n# %s\n' %
       
  1619                 (real_sitecustomize_path,))
       
  1620             sitecustomize.write(real_sitecustomize.read())
       
  1621             real_sitecustomize.close()
       
  1622     sitecustomize.close()
       
  1623     return sitecustomize_path
       
  1624 
       
  1625 def _generate_site(dest, working_set, executable, extra_paths=(),
       
  1626                    include_site_packages=False, relative_paths=False):
       
  1627     """Write a site.py file with eggs from working_set.
       
  1628 
       
  1629     extra_paths will be added to the path.  If include_site_packages is True,
       
  1630     paths from the underlying Python will be added.
       
  1631     """
       
  1632     path = _get_path(working_set, extra_paths)
       
  1633     site_path = os.path.join(dest, 'site.py')
       
  1634     original_path_setup = preamble = ''
       
  1635     if include_site_packages:
       
  1636         stdlib, site_paths = _get_system_paths(executable)
       
  1637         # We want to make sure that paths from site-packages, such as those
       
  1638         # allowed by allowed_eggs_from_site_packages, always come last, or
       
  1639         # else site-packages paths may include packages that mask the eggs we
       
  1640         # really want.
       
  1641         path = [p for p in path if p not in site_paths]
       
  1642         # Now we set up the code we need.
       
  1643         original_path_setup = original_path_snippet % (
       
  1644             _format_paths((repr(p) for p in site_paths), 2),)
       
  1645         distribution = working_set.find(
       
  1646             pkg_resources.Requirement.parse('setuptools'))
       
  1647         if distribution is not None:
       
  1648             # We need to worry about namespace packages.
       
  1649             if relative_paths:
       
  1650                 location = _relativitize(
       
  1651                     distribution.location,
       
  1652                     os.path.normcase(os.path.abspath(site_path)),
       
  1653                     relative_paths)
       
  1654             else:
       
  1655                 location = repr(distribution.location)
       
  1656             preamble = namespace_include_site_packages_setup % (location,)
       
  1657             original_path_setup = (
       
  1658                 addsitedir_namespace_originalpackages_snippet +
       
  1659                 original_path_setup)
       
  1660         else:
       
  1661             preamble = '\n    setuptools_path = None'
       
  1662     egg_path_string, relative_preamble = _relative_path_and_setup(
       
  1663         site_path, path, relative_paths, indent_level=2, omit_os_import=True)
       
  1664     if relative_preamble:
       
  1665         relative_preamble = '\n'.join(
       
  1666             [(line and '    %s' % (line,) or line)
       
  1667              for line in relative_preamble.split('\n')])
       
  1668         preamble = relative_preamble + preamble
       
  1669     addsitepackages_marker = 'def addsitepackages('
       
  1670     enableusersite_marker = 'ENABLE_USER_SITE = '
       
  1671     successful_rewrite = False
       
  1672     real_site_path = _get_module_file(executable, 'site')
       
  1673     real_site = open(real_site_path, 'r')
       
  1674     site = open(site_path, 'w')
       
  1675     try:
       
  1676         for line in real_site.readlines():
       
  1677             if line.startswith(enableusersite_marker):
       
  1678                 site.write(enableusersite_marker)
       
  1679                 site.write('False # buildout does not support user sites.\n')
       
  1680             elif line.startswith(addsitepackages_marker):
       
  1681                 site.write(addsitepackages_script % (
       
  1682                     preamble, egg_path_string, original_path_setup))
       
  1683                 site.write(line[len(addsitepackages_marker):])
       
  1684                 successful_rewrite = True
       
  1685             else:
       
  1686                 site.write(line)
       
  1687     finally:
       
  1688         site.close()
       
  1689         real_site.close()
       
  1690     if not successful_rewrite:
       
  1691         raise RuntimeError(
       
  1692             'Buildout did not successfully rewrite %s to %s' %
       
  1693             (real_site_path, site_path))
       
  1694     return site_path
       
  1695 
       
  1696 namespace_include_site_packages_setup = '''
       
  1697     setuptools_path = %s
       
  1698     sys.path.append(setuptools_path)
       
  1699     known_paths.add(os.path.normcase(setuptools_path))
       
  1700     import pkg_resources'''
       
  1701 
       
  1702 addsitedir_namespace_originalpackages_snippet = '''
       
  1703             pkg_resources.working_set.add_entry(sitedir)'''
       
  1704 
       
  1705 original_path_snippet = '''
       
  1706     sys.__egginsert = len(buildout_paths) # Support distribute.
       
  1707     original_paths = [
       
  1708         %s
       
  1709         ]
       
  1710     for path in original_paths:
       
  1711         if path == setuptools_path or path not in known_paths:
       
  1712             addsitedir(path, known_paths)'''
       
  1713 
       
  1714 addsitepackages_script = '''\
       
  1715 def addsitepackages(known_paths):
       
  1716     """Add site packages, as determined by zc.buildout.
       
  1717 
       
  1718     See original_addsitepackages, below, for the original version."""%s
       
  1719     buildout_paths = [
       
  1720         %s
       
  1721         ]
       
  1722     for path in buildout_paths:
       
  1723         sitedir, sitedircase = makepath(path)
       
  1724         if not sitedircase in known_paths and os.path.exists(sitedir):
       
  1725             sys.path.append(sitedir)
       
  1726             known_paths.add(sitedircase)%s
       
  1727     return known_paths
       
  1728 
       
  1729 def original_addsitepackages('''
       
  1730 
       
  1731 def _generate_interpreter(name, dest, executable, site_py_dest,
       
  1732                           relative_paths=False):
       
  1733     """Write an interpreter script, using the site.py approach."""
       
  1734     full_name = os.path.join(dest, name)
       
  1735     site_py_dest_string, rpsetup = _relative_path_and_setup(
       
  1736         full_name, [site_py_dest], relative_paths, omit_os_import=True)
       
  1737     if rpsetup:
       
  1738         rpsetup += "\n"
       
  1739     if sys.platform == 'win32':
       
  1740         windows_import = '\nimport subprocess'
       
  1741         # os.exec* is a mess on Windows, particularly if the path
       
  1742         # to the executable has spaces and the Python is using MSVCRT.
       
  1743         # The standard fix is to surround the executable's path with quotes,
       
  1744         # but that has been unreliable in testing.
       
  1745         #
       
  1746         # Here's a demonstration of the problem.  Given a Python
       
  1747         # compiled with a MSVCRT-based compiler, such as the free Visual
       
  1748         # C++ 2008 Express Edition, and an executable path with spaces
       
  1749         # in it such as the below, we see the following.
       
  1750         #
       
  1751         # >>> import os
       
  1752         # >>> p0 = 'C:\\Documents and Settings\\Administrator\\My Documents\\Downloads\\Python-2.6.4\\PCbuild\\python.exe'
       
  1753         # >>> os.path.exists(p0)
       
  1754         # True
       
  1755         # >>> os.execv(p0, [])
       
  1756         # Traceback (most recent call last):
       
  1757         #  File "<stdin>", line 1, in <module>
       
  1758         # OSError: [Errno 22] Invalid argument
       
  1759         #
       
  1760         # That seems like a standard problem.  The standard solution is
       
  1761         # to quote the path (see, for instance
       
  1762         # http://bugs.python.org/issue436259).  However, this solution,
       
  1763         # and other variations, fail:
       
  1764         #
       
  1765         # >>> p1 = '"C:\\Documents and Settings\\Administrator\\My Documents\\Downloads\\Python-2.6.4\\PCbuild\\python.exe"'
       
  1766         # >>> os.execv(p1, [])
       
  1767         # Traceback (most recent call last):
       
  1768         #   File "<stdin>", line 1, in <module>
       
  1769         # OSError: [Errno 22] Invalid argument
       
  1770         #
       
  1771         # We simply use subprocess instead, since it handles everything
       
  1772         # nicely, and the transparency of exec* (that is, not running,
       
  1773         # perhaps unexpectedly, in a subprocess) is arguably not a
       
  1774         # necessity, at least for many use cases.
       
  1775         execute = 'subprocess.call(argv, env=environ)'
       
  1776     else:
       
  1777         windows_import = ''
       
  1778         execute = 'os.execve(sys.executable, argv, environ)'
       
  1779     contents = interpreter_template % dict(
       
  1780         python=_safe_arg(executable),
       
  1781         dash_S=' -S',
       
  1782         site_dest=site_py_dest_string,
       
  1783         relative_paths_setup=rpsetup,
       
  1784         windows_import=windows_import,
       
  1785         execute=execute,
       
  1786         )
       
  1787     return _write_script(full_name, contents, 'interpreter')
       
  1788 
       
  1789 interpreter_template = script_header + '''
       
  1790 import os
       
  1791 import sys%(windows_import)s
       
  1792 %(relative_paths_setup)s
       
  1793 argv = [sys.executable] + sys.argv[1:]
       
  1794 environ = os.environ.copy()
       
  1795 path = %(site_dest)s
       
  1796 if environ.get('PYTHONPATH'):
       
  1797     path = os.pathsep.join([path, environ['PYTHONPATH']])
       
  1798 environ['PYTHONPATH'] = path
       
  1799 %(execute)s
       
  1800 '''
       
  1801 
       
  1802 # End of script generation code.
       
  1803 ############################################################################
       
  1804 
       
  1805 runsetup_template = """
       
  1806 import sys
       
  1807 sys.path.insert(0, %(setupdir)r)
       
  1808 sys.path.insert(0, %(setuptools)r)
       
  1809 import os, setuptools
       
  1810 
       
  1811 __file__ = %(__file__)r
       
  1812 
       
  1813 os.chdir(%(setupdir)r)
       
  1814 sys.argv[0] = %(setup)r
       
  1815 execfile(%(setup)r)
       
  1816 """
       
  1817 
       
  1818 
       
  1819 class VersionConflict(zc.buildout.UserError):
       
  1820 
       
  1821     def __init__(self, err, ws):
       
  1822         ws = list(ws)
       
  1823         ws.sort()
       
  1824         self.err, self.ws = err, ws
       
  1825 
       
  1826     def __str__(self):
       
  1827         existing_dist, req = self.err
       
  1828         result = ["There is a version conflict.",
       
  1829                   "We already have: %s" % existing_dist,
       
  1830                   ]
       
  1831         for dist in self.ws:
       
  1832             if req in dist.requires():
       
  1833                 result.append("but %s requires %r." % (dist, str(req)))
       
  1834         return '\n'.join(result)
       
  1835 
       
  1836 
       
  1837 class MissingDistribution(zc.buildout.UserError):
       
  1838 
       
  1839     def __init__(self, req, ws):
       
  1840         ws = list(ws)
       
  1841         ws.sort()
       
  1842         self.data = req, ws
       
  1843 
       
  1844     def __str__(self):
       
  1845         req, ws = self.data
       
  1846         return "Couldn't find a distribution for %r." % str(req)
       
  1847 
       
  1848 def _log_requirement(ws, req):
       
  1849     ws = list(ws)
       
  1850     ws.sort()
       
  1851     for dist in ws:
       
  1852         if req in dist.requires():
       
  1853             logger.debug("  required by %s." % dist)
       
  1854 
       
  1855 def _fix_file_links(links):
       
  1856     for link in links:
       
  1857         if link.startswith('file://') and link[-1] != '/':
       
  1858             if os.path.isdir(link[7:]):
       
  1859                 # work around excessive restriction in setuptools:
       
  1860                 link += '/'
       
  1861         yield link
       
  1862 
       
  1863 _final_parts = '*final-', '*final'
       
  1864 def _final_version(parsed_version):
       
  1865     for part in parsed_version:
       
  1866         if (part[:1] == '*') and (part not in _final_parts):
       
  1867             return False
       
  1868     return True
       
  1869 
       
  1870 def redo_pyc(egg):
       
  1871     if not os.path.isdir(egg):
       
  1872         return
       
  1873     for dirpath, dirnames, filenames in os.walk(egg):
       
  1874         for filename in filenames:
       
  1875             if not filename.endswith('.py'):
       
  1876                 continue
       
  1877             filepath = os.path.join(dirpath, filename)
       
  1878             if not (os.path.exists(filepath+'c')
       
  1879                     or os.path.exists(filepath+'o')):
       
  1880                 # If it wasn't compiled, it may not be compilable
       
  1881                 continue
       
  1882 
       
  1883             # OK, it looks like we should try to compile.
       
  1884 
       
  1885             # Remove old files.
       
  1886             for suffix in 'co':
       
  1887                 if os.path.exists(filepath+suffix):
       
  1888                     os.remove(filepath+suffix)
       
  1889 
       
  1890             # Compile under current optimization
       
  1891             try:
       
  1892                 py_compile.compile(filepath)
       
  1893             except py_compile.PyCompileError:
       
  1894                 logger.warning("Couldn't compile %s", filepath)
       
  1895             else:
       
  1896                 # Recompile under other optimization. :)
       
  1897                 args = [_safe_arg(sys.executable)]
       
  1898                 if __debug__:
       
  1899                     args.append('-O')
       
  1900                 args.extend(['-m', 'py_compile', _safe_arg(filepath)])
       
  1901 
       
  1902                 if is_jython:
       
  1903                     subprocess.call([sys.executable, args])
       
  1904                 else:
       
  1905                     os.spawnv(os.P_WAIT, sys.executable, args)
       
  1906