bootstrap.py
changeset 0 15b51dd45bab
child 33 ab440460b11b
equal deleted inserted replaced
-1:000000000000 0:15b51dd45bab
       
     1 ##############################################################################
       
     2 #
       
     3 # Copyright (c) 2006 Zope Foundation 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 """Bootstrap a buildout-based project
       
    15 
       
    16 Simply run this script in a directory containing a buildout.cfg.
       
    17 The script accepts buildout command-line options, so you can
       
    18 use the -c option to specify an alternate configuration file.
       
    19 """
       
    20 
       
    21 import os
       
    22 import shutil
       
    23 import sys
       
    24 import tempfile
       
    25 
       
    26 from optparse import OptionParser
       
    27 
       
    28 tmpeggs = tempfile.mkdtemp()
       
    29 
       
    30 usage = '''\
       
    31 [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
       
    32 
       
    33 Bootstraps a buildout-based project.
       
    34 
       
    35 Simply run this script in a directory containing a buildout.cfg, using the
       
    36 Python that you want bin/buildout to use.
       
    37 
       
    38 Note that by using --find-links to point to local resources, you can keep 
       
    39 this script from going over the network.
       
    40 '''
       
    41 
       
    42 parser = OptionParser(usage=usage)
       
    43 parser.add_option("-v", "--version", help="use a specific zc.buildout version")
       
    44 
       
    45 parser.add_option("-t", "--accept-buildout-test-releases",
       
    46                   dest='accept_buildout_test_releases',
       
    47                   action="store_true", default=False,
       
    48                   help=("Normally, if you do not specify a --version, the "
       
    49                         "bootstrap script and buildout gets the newest "
       
    50                         "*final* versions of zc.buildout and its recipes and "
       
    51                         "extensions for you.  If you use this flag, "
       
    52                         "bootstrap and buildout will get the newest releases "
       
    53                         "even if they are alphas or betas."))
       
    54 parser.add_option("-c", "--config-file",
       
    55                   help=("Specify the path to the buildout configuration "
       
    56                         "file to be used."))
       
    57 parser.add_option("-f", "--find-links",
       
    58                   help=("Specify a URL to search for buildout releases"))
       
    59 parser.add_option("--allow-site-packages",
       
    60                   action="store_true", default=False,
       
    61                   help=("Let bootstrap.py use existing site packages"))
       
    62 
       
    63 
       
    64 options, args = parser.parse_args()
       
    65 
       
    66 ######################################################################
       
    67 # load/install setuptools
       
    68 
       
    69 try:
       
    70     if options.allow_site_packages:
       
    71         import setuptools
       
    72         import pkg_resources
       
    73     from urllib.request import urlopen
       
    74 except ImportError:
       
    75     from urllib2 import urlopen
       
    76 
       
    77 ez = {}
       
    78 exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
       
    79 
       
    80 if not options.allow_site_packages:
       
    81     # ez_setup imports site, which adds site packages
       
    82     # this will remove them from the path to ensure that incompatible versions 
       
    83     # of setuptools are not in the path
       
    84     import site
       
    85     # inside a virtualenv, there is no 'getsitepackages'. 
       
    86     # We can't remove these reliably
       
    87     if hasattr(site, 'getsitepackages'):
       
    88         for sitepackage_path in site.getsitepackages():
       
    89             sys.path[:] = [x for x in sys.path if sitepackage_path not in x]
       
    90 
       
    91 setup_args = dict(to_dir=tmpeggs, download_delay=0)
       
    92 ez['use_setuptools'](**setup_args)
       
    93 import setuptools
       
    94 import pkg_resources
       
    95 
       
    96 # This does not (always?) update the default working set.  We will
       
    97 # do it.
       
    98 for path in sys.path:
       
    99     if path not in pkg_resources.working_set.entries:
       
   100         pkg_resources.working_set.add_entry(path)
       
   101 
       
   102 ######################################################################
       
   103 # Install buildout
       
   104 
       
   105 ws = pkg_resources.working_set
       
   106 
       
   107 cmd = [sys.executable, '-c',
       
   108        'from setuptools.command.easy_install import main; main()',
       
   109        '-mZqNxd', tmpeggs]
       
   110 
       
   111 find_links = os.environ.get(
       
   112     'bootstrap-testing-find-links',
       
   113     options.find_links or
       
   114     ('http://downloads.buildout.org/'
       
   115      if options.accept_buildout_test_releases else None)
       
   116     )
       
   117 if find_links:
       
   118     cmd.extend(['-f', find_links])
       
   119 
       
   120 setuptools_path = ws.find(
       
   121     pkg_resources.Requirement.parse('setuptools')).location
       
   122 
       
   123 requirement = 'zc.buildout'
       
   124 version = options.version
       
   125 if version is None and not options.accept_buildout_test_releases:
       
   126     # Figure out the most recent final version of zc.buildout.
       
   127     import setuptools.package_index
       
   128     _final_parts = '*final-', '*final'
       
   129 
       
   130     def _final_version(parsed_version):
       
   131         for part in parsed_version:
       
   132             if (part[:1] == '*') and (part not in _final_parts):
       
   133                 return False
       
   134         return True
       
   135     index = setuptools.package_index.PackageIndex(
       
   136         search_path=[setuptools_path])
       
   137     if find_links:
       
   138         index.add_find_links((find_links,))
       
   139     req = pkg_resources.Requirement.parse(requirement)
       
   140     if index.obtain(req) is not None:
       
   141         best = []
       
   142         bestv = None
       
   143         for dist in index[req.project_name]:
       
   144             distv = dist.parsed_version
       
   145             if _final_version(distv):
       
   146                 if bestv is None or distv > bestv:
       
   147                     best = [dist]
       
   148                     bestv = distv
       
   149                 elif distv == bestv:
       
   150                     best.append(dist)
       
   151         if best:
       
   152             best.sort()
       
   153             version = best[-1].version
       
   154 if version:
       
   155     requirement = '=='.join((requirement, version))
       
   156 cmd.append(requirement)
       
   157 
       
   158 import subprocess
       
   159 if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0:
       
   160     raise Exception(
       
   161         "Failed to execute command:\n%s" % repr(cmd)[1:-1])
       
   162 
       
   163 ######################################################################
       
   164 # Import and run buildout
       
   165 
       
   166 ws.add_entry(tmpeggs)
       
   167 ws.require(requirement)
       
   168 import zc.buildout.buildout
       
   169 
       
   170 if not [a for a in args if '=' not in a]:
       
   171     args.append('bootstrap')
       
   172 
       
   173 # if -c was provided, we push it back into args for buildout' main function
       
   174 if options.config_file is not None:
       
   175     args[0:0] = ['-c', options.config_file]
       
   176 
       
   177 zc.buildout.buildout.main(args)
       
   178 shutil.rmtree(tmpeggs)