OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python |
| 2 |
| 3 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 4 # for details. All rights reserved. Use of this source code is governed by a |
| 5 # BSD-style license that can be found in the LICENSE file. |
| 6 |
| 7 # Run to install the necessary components to run webdriver on the buildbots or |
| 8 # on your local machine. |
| 9 # Note: The setup steps can be done fairly easily by hand. This script is |
| 10 # intended to simply and reduce the time for setup since there are a fair number |
| 11 # of steps. |
| 12 |
| 13 # TODO(efortuna): Rewrite this script in Dart when the Process module has a |
| 14 # better high level API. |
| 15 import optparse |
| 16 import os |
| 17 import platform |
| 18 import re |
| 19 import subprocess |
| 20 import sys |
| 21 import urllib |
| 22 import urllib2 |
| 23 |
| 24 def run_cmd(cmd, stdin=None): |
| 25 """Run the command on the command line in the shell. We print the output of |
| 26 the command. |
| 27 """ |
| 28 print cmd |
| 29 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, |
| 30 stdin=subprocess.PIPE, shell=True) |
| 31 output, not_used = p.communicate(input=stdin) |
| 32 if output: |
| 33 print output |
| 34 |
| 35 def parse_args(): |
| 36 parser = optparse.OptionParser() |
| 37 parser.add_option('--firefox', '-f', dest='firefox', help='Install Firefox', |
| 38 action='store_true', default=False) |
| 39 parser.add_option('--path', '-p', dest='path', help='Specify location ' + \ |
| 40 'on your PATH for where we should install chromedriver (default is in' + \ |
| 41 'depot_tools).', metavar='CHROMEDRIVER_LOC', type='str', action='store', |
| 42 default=None) |
| 43 parser.add_option('--buildbot', '-b', dest='buildbot', action='store_true', |
| 44 help='Perform a buildbot selenium setup (buildbots have a different' + \ |
| 45 'location for their python executable).', default=False) |
| 46 args, ignored = parser.parse_args() |
| 47 return args |
| 48 |
| 49 def find_depot_tools_location(is_buildbot): |
| 50 """Depot_tools is our default install location for chromedriver, so we find |
| 51 its location on the filesystem. |
| 52 Arguments: |
| 53 is_buildbot - True if we are running buildbot machine setup (we can't detect |
| 54 this automatically because this script is not run at build time). |
| 55 """ |
| 56 if is_buildbot: |
| 57 depot_tools = os.path.join('b', 'depot_tools') |
| 58 if 'win32' in sys.platform or 'cygwin' in sys.platform: |
| 59 depot_tools = os.path.join('e:', depot_tools) |
| 60 depot_tools = '/Users/efortuna' |
| 61 return depot_tools |
| 62 else: |
| 63 path = os.environ['PATH'].split(os.pathsep) |
| 64 for loc in path: |
| 65 if 'depot_tools' in loc: |
| 66 return loc |
| 67 raise Exception("Could not find depot_tools in your path.") |
| 68 |
| 69 |
| 70 class GoogleCodeInstaller(object): |
| 71 """Install code that is being hosted on Google Code.""" |
| 72 |
| 73 def __init__(self, project_name, download_location, download_name_func): |
| 74 """ Create a object that will install code from a Google Code site. |
| 75 Arguments: |
| 76 project_name - The GoogleCode project name such as "selenium" or "chromium." |
| 77 download_location - Where to download the desired file on our filesystem. |
| 78 download_name_func - A function that takes a dictionary (currently with keys |
| 79 "os" and "version", but more can be added) that calculates the string |
| 80 representing the name of the download we want. |
| 81 """ |
| 82 self.project_name = project_name |
| 83 self.download_location = download_location |
| 84 self.download_name_func = download_name_func |
| 85 self.download_regex_str = self.download_name_func({'os': self.get_os_str, |
| 86 'version': '.+'}) |
| 87 |
| 88 def google_code_downloads_page(self): |
| 89 return 'http://code.google.com/p/%s/downloads/list' % self.project_name |
| 90 |
| 91 def google_code_download(self): |
| 92 return 'http://%s.googlecode.com/files/' % self.project_name |
| 93 |
| 94 def find_latest_version(self): |
| 95 """Find the latest version number of some code available for download on a |
| 96 Google code page. This was unfortunately done in an ad hoc manner because |
| 97 Google Code does not seem to have an API for their list of current |
| 98 downloads(!). |
| 99 """ |
| 100 google_code_site = self.google_code_downloads_page() |
| 101 f = urllib2.urlopen(google_code_site) |
| 102 latest = '' |
| 103 for line in f.readlines(): |
| 104 if re.search(self.download_regex_str, line): |
| 105 suffix_index = line.find( |
| 106 self.download_regex_str[self.download_regex_str.rfind('.'):]) |
| 107 name_end = self.download_regex_str.rfind('.+') |
| 108 name = self.download_name_func({'os': self.get_os_str, 'version': ''}) |
| 109 name = name[:name.rfind('.')] |
| 110 version_str = line[line.find(name) + len(name) : suffix_index] |
| 111 if latest == '': |
| 112 latest = '0.' * version_str.count('.') |
| 113 latest += '0' |
| 114 nums = version_str.split('.') |
| 115 latest_nums = latest.split('.') |
| 116 for (num, latest_num) in zip(nums, latest_nums): |
| 117 if int(num) > int(latest_num): |
| 118 latest = version_str |
| 119 break |
| 120 if latest == '': |
| 121 raise Exception("Couldn't find the desired download on " + \ |
| 122 ' %s.' % google_code_site) |
| 123 return latest |
| 124 |
| 125 def run(self): |
| 126 """Download and install the Google Code.""" |
| 127 print 'Installing from %s' % self.project_name |
| 128 os_str = self.get_os_str |
| 129 version = self.find_latest_version() |
| 130 download_name = self.download_name_func({'os': os_str, 'version': version}) |
| 131 urllib.urlretrieve(self.google_code_download() + '/' + download_name, |
| 132 os.path.join(self.download_location, download_name)) |
| 133 if download_name.endswith('.zip'): |
| 134 run_cmd('unzip -u %s -d %s' % (os.path.join(self.download_location, |
| 135 download_name), self.download_location)) |
| 136 os.remove(os.path.join(self.download_location, download_name)) |
| 137 |
| 138 @property |
| 139 def get_os_str(self): |
| 140 """The strings to indicate what OS a download is for as used on Google Code. |
| 141 """ |
| 142 os_str = 'win' |
| 143 if 'darwin' in sys.platform: |
| 144 os_str = 'mac' |
| 145 elif 'linux' in sys.platform: |
| 146 os_str = 'linux32' |
| 147 if '64bit' in platform.architecture()[0]: |
| 148 os_str = 'linux64' |
| 149 return os_str |
| 150 |
| 151 |
| 152 class FirefoxInstaller(object): |
| 153 """Installs the latest version of Firefox on the machine.""" |
| 154 |
| 155 def ff_download_site(self, os_name): |
| 156 return 'http://releases.mozilla.org/pub/mozilla.org/firefox/releases/' + \ |
| 157 'latest/%s/en-US/' % os_name |
| 158 |
| 159 def get_os_str(self): |
| 160 """Returns the string that Mozilla uses to denote which operating system a |
| 161 Firefox binary is for.""" |
| 162 os_str = ('win32', '.exe') |
| 163 if 'darwin' in sys.platform: |
| 164 os_str = ('mac', '.dmg') |
| 165 elif 'linux' in sys.platform: |
| 166 os_str = ('linux-i686', '.tar.bz2') |
| 167 if '64bit' in platform.architecture()[0]: |
| 168 os_str = ('linux-x86_64', '.tar.bz2') |
| 169 return os_str |
| 170 |
| 171 def get_download_url(self): |
| 172 """Parse the html on the page to determine what is the latest download |
| 173 appropriate for our system.""" |
| 174 f = urllib2.urlopen(self.ff_download_site(self.get_os_str[0])) |
| 175 download_name = '' |
| 176 for line in f.readlines(): |
| 177 suffix = self.get_os_str[1] |
| 178 if (suffix + '"') in line: |
| 179 link_str = '<a href="' |
| 180 download_name = line[line.find(link_str) + len(link_str) : \ |
| 181 line.find(suffix) + len(suffix)] |
| 182 break |
| 183 return '%s%s' % (self.ff_download_site(self.get_os_str[0]), download_name) |
| 184 |
| 185 def run(self): |
| 186 print 'Installing Firefox' |
| 187 if 'darwin' in sys.platform: |
| 188 urllib.urlretrieve(self.get_download_url(), 'firefox.dmg') |
| 189 run_cmd('hdiutil mount firefox.dmg') |
| 190 run_cmd('sudo cp -R /Volumes/firefox/Firefox.app /Applications') |
| 191 run_cmd('hdiutil unmount /Volumes/firefox/') |
| 192 elif 'win' in sys.platform: |
| 193 urllib.urlretrieve(self.get_download_url(), 'firefox_install.exe') |
| 194 run_cmd('firefox_install.exe -ms') |
| 195 else: |
| 196 run_cmd('wget -O - %s | tar -C ~ -jxv' % self.get_download_url()) |
| 197 |
| 198 |
| 199 class SeleniumBindingsInstaller(object): |
| 200 """Install the Selenium Webdriver bindings for Python.""" |
| 201 |
| 202 SETUPTOOLS_SITE = 'http://python-distribute.org/distribute_setup.py' |
| 203 PIP_SITE = 'https://raw.github.com/pypa/pip/master/contrib/get-pip.py' |
| 204 def __init__(self, is_buildbot): |
| 205 self.is_buildbot = is_buildbot |
| 206 |
| 207 def run(self): |
| 208 print 'Installing Selenium Python Bindings' |
| 209 admin_keyword = '' |
| 210 python_cmd = 'python' |
| 211 if 'win32' not in sys.platform and 'cygwin' not in sys.platform: |
| 212 admin_keyword = 'sudo' |
| 213 else: |
| 214 # The python installation is "special" on Windows buildbots. |
| 215 if is_buildbot: |
| 216 python_cmd = os.path.join(find_depot_tools_location(is_buildbot), |
| 217 'python-bin', 'python') |
| 218 page = urllib2.urlopen(self.SETUPTOOLS_SITE) |
| 219 run_cmd('%s %s' % (admin_keyword, python_cmd), page.read()) |
| 220 page = urllib2.urlopen(self.PIP_SITE) |
| 221 run_cmd('%s %s' % (admin_keyword, python_cmd), page.read()) |
| 222 run_cmd('%s pip install -U selenium' % admin_keyword) |
| 223 |
| 224 def main(): |
| 225 args = parse_args() |
| 226 SeleniumBindingsInstaller(args.buildbot).run() |
| 227 chromedriver_loc = find_depot_tools_location(args.buildbot) |
| 228 if args.path: |
| 229 chromedriver_loc = args.path |
| 230 GoogleCodeInstaller('chromium', chromedriver_loc, |
| 231 lambda x: 'chromedriver_%(os)s_%(version)s.zip' % x).run() |
| 232 if 'darwin' in sys.platform: |
| 233 GoogleCodeInstaller('selenium', os.path.dirname(os.path.abspath(__file__)), |
| 234 lambda x: 'selenium-server-standalone-%(version)s.jar' % x).run() |
| 235 |
| 236 if args.firefox: |
| 237 FirefoxInstaller().run() |
| 238 |
| 239 if __name__ == '__main__': |
| 240 main() |
OLD | NEW |