Add benchmark for WebKit process launch times
[WebKit-https.git] / PerformanceTests / LaunchTime / thirdparty / __init__.py
1 # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
2 # Copyright (C) 2018 Apple Inc. All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions
6 # are met:
7 # 1.  Redistributions of source code must retain the above copyright
8 #     notice, this list of conditions and the following disclaimer.
9 # 2.  Redistributions in binary form must reproduce the above copyright
10 #     notice, this list of conditions and the following disclaimer in the
11 #     documentation and/or other materials provided with the distribution.
12 #
13 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
14 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
17 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24 # This module is required for Python to treat this directory as a package.
25
26 """Autoinstalls third-party code required by WebKit."""
27
28
29 import codecs
30 import json
31 import os
32 import re
33 import sys
34 import urllib2
35 import imp
36
37 from collections import namedtuple
38 from distutils import spawn
39
40 webkitpy_path = os.path.join(os.path.dirname(__file__), '../../../Tools/Scripts/webkitpy')
41 autoinstall_path = os.path.join(webkitpy_path, 'common/system/autoinstall.py')
42 filesystem_path = os.path.join(webkitpy_path, 'common/system/filesystem.py')
43
44 AutoInstaller = imp.load_source('autoinstall', autoinstall_path).AutoInstaller
45 FileSystem = imp.load_source('filesystem', filesystem_path).FileSystem
46
47 _THIRDPARTY_DIR = os.path.dirname(__file__)
48 _AUTOINSTALLED_DIR = os.path.join(_THIRDPARTY_DIR, "autoinstalled")
49
50 # Putting the autoinstall code into LaunchTime/thirdparty/__init__.py
51 # ensures that no autoinstalling occurs until a caller imports from
52 # webkitpy.thirdparty.  This is useful if the caller wants to configure
53 # logging prior to executing autoinstall code.
54
55 # FIXME: If any of these servers is offline, webkit-patch breaks (and maybe
56 # other scripts do, too). See <http://webkit.org/b/42080>.
57
58 # We put auto-installed third-party modules in this directory--
59 #
60 #     LaunchTime/thirdparty/autoinstalled
61
62 fs = FileSystem()
63 fs.maybe_make_directory(_AUTOINSTALLED_DIR)
64
65 init_path = fs.join(_AUTOINSTALLED_DIR, "__init__.py")
66 if not fs.exists(init_path):
67     fs.write_text_file(init_path, "")
68
69 readme_path = fs.join(_AUTOINSTALLED_DIR, "README")
70 if not fs.exists(readme_path):
71     fs.write_text_file(readme_path,
72         "This directory is auto-generated by WebKit and is "
73         "safe to delete.\nIt contains needed third-party Python "
74         "packages automatically downloaded from the web.")
75
76
77 class AutoinstallImportHook(object):
78     def __init__(self, filesystem=None):
79         self._fs = filesystem or FileSystem()
80
81     def _ensure_autoinstalled_dir_is_in_sys_path(self):
82         # Some packages require that the are being put somewhere under a directory in sys.path.
83         if not _AUTOINSTALLED_DIR in sys.path:
84             sys.path.insert(0, _AUTOINSTALLED_DIR)
85
86     def find_module(self, fullname, _):
87         # This method will run before each import. See http://www.python.org/dev/peps/pep-0302/
88         if '.autoinstalled' not in fullname:
89             return
90
91         # Note: all of the methods must follow the "_install_XXX" convention in
92         # order for autoinstall_everything(), below, to work properly.
93         if '.tornado' in fullname:
94             self._install_tornado()
95
96     def _install_tornado(self):
97         self._ensure_autoinstalled_dir_is_in_sys_path()
98         self._install("https://files.pythonhosted.org/packages/45/ec/f2a03a0509bcfca336bef23a3dab0d07504893af34fd13064059ba4a0503/tornado-5.1.tar.gz",
99             "tornado-5.1/tornado")
100
101     @staticmethod
102     def greater_than_equal_to_version(minimum, version):
103         for i in xrange(len(minimum.split('.'))):
104             if int(version.split('.')[i]) > int(minimum.split('.')[i]):
105                 return True
106             if int(version.split('.')[i]) < int(minimum.split('.')[i]):
107                 return False
108         return True
109
110     def _install(self, url, url_subpath=None, target_name=None):
111         installer = AutoInstaller(target_dir=_AUTOINSTALLED_DIR)
112         installer.install(url=url, url_subpath=url_subpath, target_name=target_name)
113
114     def get_latest_pypi_url(self, package_name, url_subpath_format='{name}-{version}/{lname}'):
115         json_url = "https://pypi.python.org/pypi/%s/json" % package_name
116         response = urllib2.urlopen(json_url)
117         data = json.load(response)
118         url = data['urls'][1]['url']
119         subpath = url_subpath_format.format(name=package_name, version=data['info']['version'], lname=package_name.lower())
120         return (url, subpath)
121
122     def install_binary(self, url, name):
123         self._install(url=url, target_name=name)
124         directory = os.path.join(_AUTOINSTALLED_DIR, name)
125         os.chmod(os.path.join(directory, name), 0755)
126         open(os.path.join(directory, '__init__.py'), 'w+').close()
127
128
129 _hook = AutoinstallImportHook()
130 sys.meta_path.append(_hook)
131
132
133 def autoinstall_everything():
134     install_methods = [method for method in dir(_hook.__class__) if method.startswith('_install_')]
135     for method in install_methods:
136         getattr(_hook, method)()
137
138
139 def get_os_info():
140     import platform
141     os_name = platform.system()
142     os_type = platform.machine()[-2:]
143     return (os_name, os_type)