bootstrap   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 207
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 5
eloc 122
dl 0
loc 207
rs 10
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
A _final_version() 0 9 5
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
Simply run this script in a directory containing a buildout.cfg.
16
The script accepts buildout command-line options, so you can
17
use the -c option to specify an alternate configuration file.
18
"""
19
20
import os
21
import shutil
22
import sys
23
import tempfile
24
25
from optparse import OptionParser
26
27
__version__ = '2015-07-01'
28
# See zc.buildout's changelog if this version is up to date.
29
30
tmpeggs = tempfile.mkdtemp(prefix='bootstrap-')
31
32
usage = '''\
33
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
34
Bootstraps a buildout-based project.
35
Simply run this script in a directory containing a buildout.cfg, using the
36
Python that you want bin/buildout to use.
37
Note that by using --find-links to point to local resources, you can keep
38
this script from going over the network.
39
'''
40
41
parser = OptionParser(usage=usage)
42
parser.add_option("--version",
43
                  action="store_true", default=False,
44
                  help=("Return bootstrap.py version."))
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
parser.add_option("--buildout-version",
63
                  help="Use a specific zc.buildout version")
64
parser.add_option("--setuptools-version",
65
                  help="Use a specific setuptools version")
66
parser.add_option("--setuptools-to-dir",
67
                  help=("Allow for re-use of existing directory of "
68
                        "setuptools versions"))
69
70
options, args = parser.parse_args()
71
if options.version:
72
    print("bootstrap.py version %s" % __version__)
73
    sys.exit(0)
74
75
76
######################################################################
77
# load/install setuptools
78
79
try:
80
    from urllib.request import urlopen
81
except ImportError:
82
    from urllib2 import urlopen
83
84
ez = {}
85
if os.path.exists('ez_setup.py'):
86
    exec(open('ez_setup.py').read(), ez)
87
else:
88
    exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
89
90
if not options.allow_site_packages:
91
    # ez_setup imports site, which adds site packages
92
    # this will remove them from the path to ensure that incompatible versions
93
    # of setuptools are not in the path
94
    import site
95
    # inside a virtualenv, there is no 'getsitepackages'.
96
    # We can't remove these reliably
97
    if hasattr(site, 'getsitepackages'):
98
        for sitepackage_path in site.getsitepackages():
99
            # Strip all site-packages directories from sys.path that
100
            # are not sys.prefix; this is because on Windows
101
            # sys.prefix is a site-package directory.
102
            if sitepackage_path != sys.prefix:
103
                sys.path[:] = [x for x in sys.path
104
                               if sitepackage_path not in x]
105
106
setup_args = dict(to_dir=tmpeggs, download_delay=0)
107
108
if options.setuptools_version is not None:
109
    setup_args['version'] = options.setuptools_version
110
if options.setuptools_to_dir is not None:
111
    setup_args['to_dir'] = options.setuptools_to_dir
112
113
ez['use_setuptools'](**setup_args)
114
import setuptools
115
import pkg_resources
116
117
# This does not (always?) update the default working set.  We will
118
# do it.
119
for path in sys.path:
120
    if path not in pkg_resources.working_set.entries:
121
        pkg_resources.working_set.add_entry(path)
122
123
######################################################################
124
# Install buildout
125
126
ws = pkg_resources.working_set
127
128
setuptools_path = ws.find(
129
    pkg_resources.Requirement.parse('setuptools')).location
130
131
# Fix sys.path here as easy_install.pth added before PYTHONPATH
132
cmd = [sys.executable, '-c',
133
       'import sys; sys.path[0:0] = [%r]; ' % setuptools_path +
134
       'from setuptools.command.easy_install import main; main()',
135
       '-mZqNxd', tmpeggs]
136
137
find_links = os.environ.get(
138
    'bootstrap-testing-find-links',
139
    options.find_links or
140
    ('http://downloads.buildout.org/'
141
     if options.accept_buildout_test_releases else None)
142
    )
143
if find_links:
144
    cmd.extend(['-f', find_links])
145
146
requirement = 'zc.buildout'
147
version = options.buildout_version
148
if version is None and not options.accept_buildout_test_releases:
149
    # Figure out the most recent final version of zc.buildout.
150
    import setuptools.package_index
151
    _final_parts = '*final-', '*final'
152
153
    def _final_version(parsed_version):
154
        try:
155
            return not parsed_version.is_prerelease
156
        except AttributeError:
157
            # Older setuptools
158
            for part in parsed_version:
159
                if (part[:1] == '*') and (part not in _final_parts):
160
                    return False
161
            return True
162
163
    index = setuptools.package_index.PackageIndex(
164
        search_path=[setuptools_path])
165
    if find_links:
166
        index.add_find_links((find_links,))
167
    req = pkg_resources.Requirement.parse(requirement)
168
    if index.obtain(req) is not None:
169
        best = []
170
        bestv = None
171
        for dist in index[req.project_name]:
172
            distv = dist.parsed_version
173
            if _final_version(distv):
174
                if bestv is None or distv > bestv:
175
                    best = [dist]
176
                    bestv = distv
177
                elif distv == bestv:
178
                    best.append(dist)
179
        if best:
180
            best.sort()
181
            version = best[-1].version
182
if version:
183
    requirement = '=='.join((requirement, version))
184
cmd.append(requirement)
185
186
import subprocess
187
if subprocess.call(cmd) != 0:
188
    raise Exception(
189
        "Failed to execute command:\n%s" % repr(cmd)[1:-1])
190
191
######################################################################
192
# Import and run buildout
193
194
ws.add_entry(tmpeggs)
195
ws.require(requirement)
196
import zc.buildout.buildout
197
198
if not [a for a in args if '=' not in a]:
199
    args.append('bootstrap')
200
201
# if -c was provided, we push it back into args for buildout' main function
202
if options.config_file is not None:
203
    args[0:0] = ['-c', options.config_file]
204
205
zc.buildout.buildout.main(args)
206
shutil.rmtree(tmpeggs)
207