This patch is used to add grafana config to opnfv dashboard for
[yardstick.git] / ez_setup.py
1 #!/usr/bin/env python
2 """Bootstrap setuptools installation
3
4 To use setuptools in your package's setup.py, include this
5 file in the same directory and add this to the top of your setup.py::
6
7     from ez_setup import use_setuptools
8     use_setuptools()
9
10 To require a specific version of setuptools, set a download
11 mirror, or use an alternate download directory, simply supply
12 the appropriate options to ``use_setuptools()``.
13
14 This file can also be run as a script to install or upgrade setuptools.
15 """
16 import os
17 import shutil
18 import sys
19 import tempfile
20 import zipfile
21 import optparse
22 import subprocess
23 import platform
24 import textwrap
25 import contextlib
26
27 from distutils import log
28
29 try:
30     from urllib.request import urlopen
31 except ImportError:
32     from urllib2 import urlopen
33
34 try:
35     from site import USER_SITE
36 except ImportError:
37     USER_SITE = None
38
39 DEFAULT_VERSION = "6.1"
40 DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
41
42 def _python_cmd(*args):
43     """
44     Return True if the command succeeded.
45     """
46     args = (sys.executable,) + args
47     return subprocess.call(args) == 0
48
49
50 def _install(archive_filename, install_args=()):
51     with archive_context(archive_filename):
52         # installing
53         log.warn('Installing Setuptools')
54         if not _python_cmd('setup.py', 'install', *install_args):
55             log.warn('Something went wrong during the installation.')
56             log.warn('See the error message above.')
57             # exitcode will be 2
58             return 2
59
60
61 def _build_egg(egg, archive_filename, to_dir):
62     with archive_context(archive_filename):
63         # building an egg
64         log.warn('Building a Setuptools egg in %s', to_dir)
65         _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
66     # returning the result
67     log.warn(egg)
68     if not os.path.exists(egg):
69         raise IOError('Could not build the egg.')
70
71
72 class ContextualZipFile(zipfile.ZipFile):
73     """
74     Supplement ZipFile class to support context manager for Python 2.6
75     """
76
77     def __enter__(self):
78         return self
79
80     def __exit__(self, type, value, traceback):
81         self.close()
82
83     def __new__(cls, *args, **kwargs):
84         """
85         Construct a ZipFile or ContextualZipFile as appropriate
86         """
87         if hasattr(zipfile.ZipFile, '__exit__'):
88             return zipfile.ZipFile(*args, **kwargs)
89         return super(ContextualZipFile, cls).__new__(cls)
90
91
92 @contextlib.contextmanager
93 def archive_context(filename):
94     # extracting the archive
95     tmpdir = tempfile.mkdtemp()
96     log.warn('Extracting in %s', tmpdir)
97     old_wd = os.getcwd()
98     try:
99         os.chdir(tmpdir)
100         with ContextualZipFile(filename) as archive:
101             archive.extractall()
102
103         # going in the directory
104         subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
105         os.chdir(subdir)
106         log.warn('Now working in %s', subdir)
107         yield
108
109     finally:
110         os.chdir(old_wd)
111         shutil.rmtree(tmpdir)
112
113
114 def _do_download(version, download_base, to_dir, download_delay):
115     egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg'
116                        % (version, sys.version_info[0], sys.version_info[1]))
117     if not os.path.exists(egg):
118         archive = download_setuptools(version, download_base,
119                                       to_dir, download_delay)
120         _build_egg(egg, archive, to_dir)
121     sys.path.insert(0, egg)
122
123     # Remove previously-imported pkg_resources if present (see
124     # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details).
125     if 'pkg_resources' in sys.modules:
126         del sys.modules['pkg_resources']
127
128     import setuptools
129     setuptools.bootstrap_install_from = egg
130
131
132 def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
133         to_dir=os.curdir, download_delay=15):
134     to_dir = os.path.abspath(to_dir)
135     rep_modules = 'pkg_resources', 'setuptools'
136     imported = set(sys.modules).intersection(rep_modules)
137     try:
138         import pkg_resources
139     except ImportError:
140         return _do_download(version, download_base, to_dir, download_delay)
141     try:
142         pkg_resources.require("setuptools>=" + version)
143         return
144     except pkg_resources.DistributionNotFound:
145         return _do_download(version, download_base, to_dir, download_delay)
146     except pkg_resources.VersionConflict as VC_err:
147         if imported:
148             msg = textwrap.dedent("""
149                 The required version of setuptools (>={version}) is not available,
150                 and can't be installed while this script is running. Please
151                 install a more recent version first, using
152                 'easy_install -U setuptools'.
153
154                 (Currently using {VC_err.args[0]!r})
155                 """).format(VC_err=VC_err, version=version)
156             sys.stderr.write(msg)
157             sys.exit(2)
158
159         # otherwise, reload ok
160         del pkg_resources, sys.modules['pkg_resources']
161         return _do_download(version, download_base, to_dir, download_delay)
162
163 def _clean_check(cmd, target):
164     """
165     Run the command to download target. If the command fails, clean up before
166     re-raising the error.
167     """
168     try:
169         subprocess.check_call(cmd)
170     except subprocess.CalledProcessError:
171         if os.access(target, os.F_OK):
172             os.unlink(target)
173         raise
174
175 def download_file_powershell(url, target):
176     """
177     Download the file at url to target using Powershell (which will validate
178     trust). Raise an exception if the command cannot complete.
179     """
180     target = os.path.abspath(target)
181     ps_cmd = (
182         "[System.Net.WebRequest]::DefaultWebProxy.Credentials = "
183         "[System.Net.CredentialCache]::DefaultCredentials; "
184         "(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)"
185         % vars()
186     )
187     cmd = [
188         'powershell',
189         '-Command',
190         ps_cmd,
191     ]
192     _clean_check(cmd, target)
193
194 def has_powershell():
195     if platform.system() != 'Windows':
196         return False
197     cmd = ['powershell', '-Command', 'echo test']
198     with open(os.path.devnull, 'wb') as devnull:
199         try:
200             subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
201         except Exception:
202             return False
203     return True
204
205 download_file_powershell.viable = has_powershell
206
207 def download_file_curl(url, target):
208     cmd = ['curl', url, '--silent', '--output', target]
209     _clean_check(cmd, target)
210
211 def has_curl():
212     cmd = ['curl', '--version']
213     with open(os.path.devnull, 'wb') as devnull:
214         try:
215             subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
216         except Exception:
217             return False
218     return True
219
220 download_file_curl.viable = has_curl
221
222 def download_file_wget(url, target):
223     cmd = ['wget', url, '--quiet', '--output-document', target]
224     _clean_check(cmd, target)
225
226 def has_wget():
227     cmd = ['wget', '--version']
228     with open(os.path.devnull, 'wb') as devnull:
229         try:
230             subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
231         except Exception:
232             return False
233     return True
234
235 download_file_wget.viable = has_wget
236
237 def download_file_insecure(url, target):
238     """
239     Use Python to download the file, even though it cannot authenticate the
240     connection.
241     """
242     src = urlopen(url)
243     try:
244         # Read all the data in one block.
245         data = src.read()
246     finally:
247         src.close()
248
249     # Write all the data in one block to avoid creating a partial file.
250     with open(target, "wb") as dst:
251         dst.write(data)
252
253 download_file_insecure.viable = lambda: True
254
255 def get_best_downloader():
256     downloaders = (
257         download_file_powershell,
258         download_file_curl,
259         download_file_wget,
260         download_file_insecure,
261     )
262     viable_downloaders = (dl for dl in downloaders if dl.viable())
263     return next(viable_downloaders, None)
264
265 def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
266         to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader):
267     """
268     Download setuptools from a specified location and return its filename
269
270     `version` should be a valid setuptools version number that is available
271     as an sdist for download under the `download_base` URL (which should end
272     with a '/'). `to_dir` is the directory where the egg will be downloaded.
273     `delay` is the number of seconds to pause before an actual download
274     attempt.
275
276     ``downloader_factory`` should be a function taking no arguments and
277     returning a function for downloading a URL to a target.
278     """
279     # making sure we use the absolute path
280     to_dir = os.path.abspath(to_dir)
281     zip_name = "setuptools-%s.zip" % version
282     url = download_base + zip_name
283     saveto = os.path.join(to_dir, zip_name)
284     if not os.path.exists(saveto):  # Avoid repeated downloads
285         log.warn("Downloading %s", url)
286         downloader = downloader_factory()
287         downloader(url, saveto)
288     return os.path.realpath(saveto)
289
290 def _build_install_args(options):
291     """
292     Build the arguments to 'python setup.py install' on the setuptools package
293     """
294     return ['--user'] if options.user_install else []
295
296 def _parse_args():
297     """
298     Parse the command line for options
299     """
300     parser = optparse.OptionParser()
301     parser.add_option(
302         '--user', dest='user_install', action='store_true', default=False,
303         help='install in user site package (requires Python 2.6 or later)')
304     parser.add_option(
305         '--download-base', dest='download_base', metavar="URL",
306         default=DEFAULT_URL,
307         help='alternative URL from where to download the setuptools package')
308     parser.add_option(
309         '--insecure', dest='downloader_factory', action='store_const',
310         const=lambda: download_file_insecure, default=get_best_downloader,
311         help='Use internal, non-validating downloader'
312     )
313     parser.add_option(
314         '--version', help="Specify which version to download",
315         default=DEFAULT_VERSION,
316     )
317     options, args = parser.parse_args()
318     # positional arguments are ignored
319     return options
320
321 def main():
322     """Install or upgrade setuptools and EasyInstall"""
323     options = _parse_args()
324     archive = download_setuptools(
325         version=options.version,
326         download_base=options.download_base,
327         downloader_factory=options.downloader_factory,
328     )
329     return _install(archive, _build_install_args(options))
330
331 if __name__ == '__main__':
332     sys.exit(main())