bootstrap.py
changeset 137 b9ac32b97fa9
parent 0 63811b2a5670
equal deleted inserted replaced
136:51ffb2e0ef3c 137:b9ac32b97fa9
    23 import sys
    23 import sys
    24 import tempfile
    24 import tempfile
    25 
    25 
    26 from optparse import OptionParser
    26 from optparse import OptionParser
    27 
    27 
    28 tmpeggs = tempfile.mkdtemp()
    28 __version__ = '2015-07-01'
       
    29 # See zc.buildout's changelog if this version is up to date.
       
    30 
       
    31 tmpeggs = tempfile.mkdtemp(prefix='bootstrap-')
    29 
    32 
    30 usage = '''\
    33 usage = '''\
    31 [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
    34 [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
    32 
    35 
    33 Bootstraps a buildout-based project.
    36 Bootstraps a buildout-based project.
    34 
    37 
    35 Simply run this script in a directory containing a buildout.cfg, using the
    38 Simply run this script in a directory containing a buildout.cfg, using the
    36 Python that you want bin/buildout to use.
    39 Python that you want bin/buildout to use.
    37 
    40 
    38 Note that by using --find-links to point to local resources, you can keep 
    41 Note that by using --find-links to point to local resources, you can keep
    39 this script from going over the network.
    42 this script from going over the network.
    40 '''
    43 '''
    41 
    44 
    42 parser = OptionParser(usage=usage)
    45 parser = OptionParser(usage=usage)
    43 parser.add_option("-v", "--version", help="use a specific zc.buildout version")
    46 parser.add_option("--version",
    44 
    47                   action="store_true", default=False,
       
    48                   help=("Return bootstrap.py version."))
    45 parser.add_option("-t", "--accept-buildout-test-releases",
    49 parser.add_option("-t", "--accept-buildout-test-releases",
    46                   dest='accept_buildout_test_releases',
    50                   dest='accept_buildout_test_releases',
    47                   action="store_true", default=False,
    51                   action="store_true", default=False,
    48                   help=("Normally, if you do not specify a --version, the "
    52                   help=("Normally, if you do not specify a --buildout-version, "
    49                         "bootstrap script and buildout gets the newest "
    53                         "the bootstrap script and buildout gets the newest "
    50                         "*final* versions of zc.buildout and its recipes and "
    54                         "*final* versions of zc.buildout and its recipes and "
    51                         "extensions for you.  If you use this flag, "
    55                         "extensions for you.  If you use this flag, "
    52                         "bootstrap and buildout will get the newest releases "
    56                         "bootstrap and buildout will get the newest releases "
    53                         "even if they are alphas or betas."))
    57                         "even if they are alphas or betas."))
    54 parser.add_option("-c", "--config-file",
    58 parser.add_option("-c", "--config-file",
    57 parser.add_option("-f", "--find-links",
    61 parser.add_option("-f", "--find-links",
    58                   help=("Specify a URL to search for buildout releases"))
    62                   help=("Specify a URL to search for buildout releases"))
    59 parser.add_option("--allow-site-packages",
    63 parser.add_option("--allow-site-packages",
    60                   action="store_true", default=False,
    64                   action="store_true", default=False,
    61                   help=("Let bootstrap.py use existing site packages"))
    65                   help=("Let bootstrap.py use existing site packages"))
    62 
    66 parser.add_option("--buildout-version",
       
    67                   help="Use a specific zc.buildout version")
       
    68 parser.add_option("--setuptools-version",
       
    69                   help="Use a specific setuptools version")
       
    70 parser.add_option("--setuptools-to-dir",
       
    71                   help=("Allow for re-use of existing directory of "
       
    72                         "setuptools versions"))
    63 
    73 
    64 options, args = parser.parse_args()
    74 options, args = parser.parse_args()
       
    75 if options.version:
       
    76     print("bootstrap.py version %s" % __version__)
       
    77     sys.exit(0)
       
    78 
    65 
    79 
    66 ######################################################################
    80 ######################################################################
    67 # load/install setuptools
    81 # load/install setuptools
    68 
    82 
    69 try:
    83 try:
    70     if options.allow_site_packages:
       
    71         import setuptools
       
    72         import pkg_resources
       
    73     from urllib.request import urlopen
    84     from urllib.request import urlopen
    74 except ImportError:
    85 except ImportError:
    75     from urllib2 import urlopen
    86     from urllib2 import urlopen
    76 
    87 
    77 ez = {}
    88 ez = {}
    78 exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
    89 if os.path.exists('ez_setup.py'):
       
    90     exec(open('ez_setup.py').read(), ez)
       
    91 else:
       
    92     exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
    79 
    93 
    80 if not options.allow_site_packages:
    94 if not options.allow_site_packages:
    81     # ez_setup imports site, which adds site packages
    95     # ez_setup imports site, which adds site packages
    82     # this will remove them from the path to ensure that incompatible versions 
    96     # this will remove them from the path to ensure that incompatible versions
    83     # of setuptools are not in the path
    97     # of setuptools are not in the path
    84     import site
    98     import site
    85     # inside a virtualenv, there is no 'getsitepackages'. 
    99     # inside a virtualenv, there is no 'getsitepackages'.
    86     # We can't remove these reliably
   100     # We can't remove these reliably
    87     if hasattr(site, 'getsitepackages'):
   101     if hasattr(site, 'getsitepackages'):
    88         for sitepackage_path in site.getsitepackages():
   102         for sitepackage_path in site.getsitepackages():
    89             sys.path[:] = [x for x in sys.path if sitepackage_path not in x]
   103             # Strip all site-packages directories from sys.path that
       
   104             # are not sys.prefix; this is because on Windows
       
   105             # sys.prefix is a site-package directory.
       
   106             if sitepackage_path != sys.prefix:
       
   107                 sys.path[:] = [x for x in sys.path
       
   108                                if sitepackage_path not in x]
    90 
   109 
    91 setup_args = dict(to_dir=tmpeggs, download_delay=0)
   110 setup_args = dict(to_dir=tmpeggs, download_delay=0)
       
   111 
       
   112 if options.setuptools_version is not None:
       
   113     setup_args['version'] = options.setuptools_version
       
   114 if options.setuptools_to_dir is not None:
       
   115     setup_args['to_dir'] = options.setuptools_to_dir
       
   116 
    92 ez['use_setuptools'](**setup_args)
   117 ez['use_setuptools'](**setup_args)
    93 import setuptools
   118 import setuptools
    94 import pkg_resources
   119 import pkg_resources
    95 
   120 
    96 # This does not (always?) update the default working set.  We will
   121 # This does not (always?) update the default working set.  We will
   102 ######################################################################
   127 ######################################################################
   103 # Install buildout
   128 # Install buildout
   104 
   129 
   105 ws = pkg_resources.working_set
   130 ws = pkg_resources.working_set
   106 
   131 
       
   132 setuptools_path = ws.find(
       
   133     pkg_resources.Requirement.parse('setuptools')).location
       
   134 
       
   135 # Fix sys.path here as easy_install.pth added before PYTHONPATH
   107 cmd = [sys.executable, '-c',
   136 cmd = [sys.executable, '-c',
       
   137        'import sys; sys.path[0:0] = [%r]; ' % setuptools_path +
   108        'from setuptools.command.easy_install import main; main()',
   138        'from setuptools.command.easy_install import main; main()',
   109        '-mZqNxd', tmpeggs]
   139        '-mZqNxd', tmpeggs]
   110 
   140 
   111 find_links = os.environ.get(
   141 find_links = os.environ.get(
   112     'bootstrap-testing-find-links',
   142     'bootstrap-testing-find-links',
   115      if options.accept_buildout_test_releases else None)
   145      if options.accept_buildout_test_releases else None)
   116     )
   146     )
   117 if find_links:
   147 if find_links:
   118     cmd.extend(['-f', find_links])
   148     cmd.extend(['-f', find_links])
   119 
   149 
   120 setuptools_path = ws.find(
       
   121     pkg_resources.Requirement.parse('setuptools')).location
       
   122 
       
   123 requirement = 'zc.buildout'
   150 requirement = 'zc.buildout'
   124 version = options.version
   151 version = options.buildout_version
   125 if version is None and not options.accept_buildout_test_releases:
   152 if version is None and not options.accept_buildout_test_releases:
   126     # Figure out the most recent final version of zc.buildout.
   153     # Figure out the most recent final version of zc.buildout.
   127     import setuptools.package_index
   154     import setuptools.package_index
   128     _final_parts = '*final-', '*final'
   155     _final_parts = '*final-', '*final'
   129 
   156 
   130     def _final_version(parsed_version):
   157     def _final_version(parsed_version):
   131         for part in parsed_version:
   158         try:
   132             if (part[:1] == '*') and (part not in _final_parts):
   159             return not parsed_version.is_prerelease
   133                 return False
   160         except AttributeError:
   134         return True
   161             # Older setuptools
       
   162             for part in parsed_version:
       
   163                 if (part[:1] == '*') and (part not in _final_parts):
       
   164                     return False
       
   165             return True
       
   166 
   135     index = setuptools.package_index.PackageIndex(
   167     index = setuptools.package_index.PackageIndex(
   136         search_path=[setuptools_path])
   168         search_path=[setuptools_path])
   137     if find_links:
   169     if find_links:
   138         index.add_find_links((find_links,))
   170         index.add_find_links((find_links,))
   139     req = pkg_resources.Requirement.parse(requirement)
   171     req = pkg_resources.Requirement.parse(requirement)
   154 if version:
   186 if version:
   155     requirement = '=='.join((requirement, version))
   187     requirement = '=='.join((requirement, version))
   156 cmd.append(requirement)
   188 cmd.append(requirement)
   157 
   189 
   158 import subprocess
   190 import subprocess
   159 if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0:
   191 if subprocess.call(cmd) != 0:
   160     raise Exception(
   192     raise Exception(
   161         "Failed to execute command:\n%s" % repr(cmd)[1:-1])
   193         "Failed to execute command:\n%s" % repr(cmd)[1:-1])
   162 
   194 
   163 ######################################################################
   195 ######################################################################
   164 # Import and run buildout
   196 # Import and run buildout