| # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) |
| # Copyright (C) 2018 Apple Inc. All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND |
| # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR |
| # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| # This module is required for Python to treat this directory as a package. |
| |
| """Autoinstalls third-party code required by WebKit.""" |
| |
| |
| import codecs |
| import json |
| import os |
| import re |
| import sys |
| import urllib2 |
| import imp |
| |
| from collections import namedtuple |
| from distutils import spawn |
| |
| webkitpy_path = os.path.join(os.path.dirname(__file__), '../../../Tools/Scripts/webkitpy') |
| autoinstall_path = os.path.join(webkitpy_path, 'common/system/autoinstall.py') |
| filesystem_path = os.path.join(webkitpy_path, 'common/system/filesystem.py') |
| |
| AutoInstaller = imp.load_source('autoinstall', autoinstall_path).AutoInstaller |
| FileSystem = imp.load_source('filesystem', filesystem_path).FileSystem |
| |
| _THIRDPARTY_DIR = os.path.dirname(__file__) |
| _AUTOINSTALLED_DIR = os.path.join(_THIRDPARTY_DIR, "autoinstalled") |
| |
| # Putting the autoinstall code into LaunchTime/thirdparty/__init__.py |
| # ensures that no autoinstalling occurs until a caller imports from |
| # webkitpy.thirdparty. This is useful if the caller wants to configure |
| # logging prior to executing autoinstall code. |
| |
| # FIXME: If any of these servers is offline, webkit-patch breaks (and maybe |
| # other scripts do, too). See <http://webkit.org/b/42080>. |
| |
| # We put auto-installed third-party modules in this directory-- |
| # |
| # LaunchTime/thirdparty/autoinstalled |
| |
| fs = FileSystem() |
| fs.maybe_make_directory(_AUTOINSTALLED_DIR) |
| |
| init_path = fs.join(_AUTOINSTALLED_DIR, "__init__.py") |
| if not fs.exists(init_path): |
| fs.write_text_file(init_path, "") |
| |
| readme_path = fs.join(_AUTOINSTALLED_DIR, "README") |
| if not fs.exists(readme_path): |
| fs.write_text_file(readme_path, |
| "This directory is auto-generated by WebKit and is " |
| "safe to delete.\nIt contains needed third-party Python " |
| "packages automatically downloaded from the web.") |
| |
| |
| class AutoinstallImportHook(object): |
| def __init__(self, filesystem=None): |
| self._fs = filesystem or FileSystem() |
| |
| def _ensure_autoinstalled_dir_is_in_sys_path(self): |
| # Some packages require that the are being put somewhere under a directory in sys.path. |
| if not _AUTOINSTALLED_DIR in sys.path: |
| sys.path.insert(0, _AUTOINSTALLED_DIR) |
| |
| def find_module(self, fullname, _): |
| # This method will run before each import. See http://www.python.org/dev/peps/pep-0302/ |
| if '.autoinstalled' not in fullname: |
| return |
| |
| # Note: all of the methods must follow the "_install_XXX" convention in |
| # order for autoinstall_everything(), below, to work properly. |
| if '.tornado' in fullname: |
| self._install_tornado() |
| |
| def _install_tornado(self): |
| self._ensure_autoinstalled_dir_is_in_sys_path() |
| self._install("https://files.pythonhosted.org/packages/45/ec/f2a03a0509bcfca336bef23a3dab0d07504893af34fd13064059ba4a0503/tornado-5.1.tar.gz", |
| "tornado-5.1/tornado") |
| |
| @staticmethod |
| def greater_than_equal_to_version(minimum, version): |
| for i in xrange(len(minimum.split('.'))): |
| if int(version.split('.')[i]) > int(minimum.split('.')[i]): |
| return True |
| if int(version.split('.')[i]) < int(minimum.split('.')[i]): |
| return False |
| return True |
| |
| def _install(self, url, url_subpath=None, target_name=None): |
| installer = AutoInstaller(target_dir=_AUTOINSTALLED_DIR) |
| installer.install(url=url, url_subpath=url_subpath, target_name=target_name) |
| |
| def get_latest_pypi_url(self, package_name, url_subpath_format='{name}-{version}/{lname}'): |
| json_url = "https://pypi.python.org/pypi/%s/json" % package_name |
| response = urllib2.urlopen(json_url) |
| data = json.load(response) |
| url = data['urls'][1]['url'] |
| subpath = url_subpath_format.format(name=package_name, version=data['info']['version'], lname=package_name.lower()) |
| return (url, subpath) |
| |
| def install_binary(self, url, name): |
| self._install(url=url, target_name=name) |
| directory = os.path.join(_AUTOINSTALLED_DIR, name) |
| os.chmod(os.path.join(directory, name), 0755) |
| open(os.path.join(directory, '__init__.py'), 'w+').close() |
| |
| |
| _hook = AutoinstallImportHook() |
| sys.meta_path.append(_hook) |
| |
| |
| def autoinstall_everything(): |
| install_methods = [method for method in dir(_hook.__class__) if method.startswith('_install_')] |
| for method in install_methods: |
| getattr(_hook, method)() |
| |
| |
| def get_os_info(): |
| import platform |
| os_name = platform.system() |
| os_type = platform.machine()[-2:] |
| return (os_name, os_type) |