#!/usr/bin/python # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file # for details. All rights reserved. Use of this source code is governed by a # BSD-style license that can be found in the LICENSE file. # Run to install the necessary components to run webdriver on the buildbots or # on your local machine. # Note: The setup steps can be done fairly easily by hand. This script is # intended to simply and reduce the time for setup since there are a fair number # of steps. # TODO(efortuna): Rewrite this script in Dart when the Process module has a # better high level API. import optparse import os import platform import re import subprocess import sys import urllib import urllib2 import zipfile def run_cmd(cmd, stdin=None): """Run the command on the command line in the shell. We print the output of the command. """ print cmd p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True) output, stderr = p.communicate(input=stdin) if output: print output if stderr: print stderr def parse_args(): parser = optparse.OptionParser() parser.add_option('--firefox', '-f', dest='firefox', help='Install Firefox', action='store_true', default=False) parser.add_option('--path', '-p', dest='path', help='Specify location ' + \ 'on your PATH for where we should install chromedriver (default is in' + \ 'depot_tools).', metavar='CHROMEDRIVER_LOC', type='str', action='store', default=None) parser.add_option('--buildbot', '-b', dest='buildbot', action='store_true', help='Perform a buildbot selenium setup (buildbots have a different' + \ 'location for their python executable).', default=False) args, ignored = parser.parse_args() return args def find_depot_tools_location(is_buildbot): """Depot_tools is our default install location for chromedriver, so we find its location on the filesystem. Arguments: is_buildbot - True if we are running buildbot machine setup (we can't detect this automatically because this script is not run at build time). """ if is_buildbot: depot_tools = os.path.join('b', 'depot_tools') if 'win32' in sys.platform or 'cygwin' in sys.platform: depot_tools = os.path.join('e:', depot_tools) return depot_tools else: path = os.environ['PATH'].split(os.pathsep) for loc in path: if 'depot_tools' in loc: return loc raise Exception("Could not find depot_tools in your path.") class GoogleCodeInstaller(object): """Install code that is being hosted on Google Code.""" def __init__(self, project_name, download_location, download_name_func): """ Create a object that will install code from a Google Code site. Arguments: project_name - The GoogleCode project name such as "selenium" or "chromedriver." download_location - Where to download the desired file on our filesystem. download_name_func - A function that takes a dictionary (currently with keys "os" and "version", but more can be added) that calculates the string representing the name of the download we want. """ self.project_name = project_name self.download_location = download_location self.download_name_func = download_name_func self.download_regex_str = self.download_name_func({'os': self.get_os_str, 'version': '.+'}) def google_code_downloads_page(self): return 'http://code.google.com/p/%s/downloads/list' % self.project_name def google_code_download(self): return 'http://%s.googlecode.com/files/' % self.project_name def find_latest_version(self): """Find the latest version number of some code available for download on a Google code page. This was unfortunately done in an ad hoc manner because Google Code does not seem to have an API for their list of current downloads(!). """ google_code_site = self.google_code_downloads_page() f = urllib2.urlopen(google_code_site) latest = '' for line in f.readlines(): if re.search(self.download_regex_str, line): suffix_index = line.find( self.download_regex_str[self.download_regex_str.rfind('.'):]) name_end = self.download_regex_str.rfind('.+') name = self.download_name_func({'os': self.get_os_str, 'version': ''}) name = name[:name.rfind('.')] version_str = line[line.find(name) + len(name) : suffix_index] if latest == '': latest = '0.' * version_str.count('.') latest += '0' nums = version_str.split('.') latest_nums = latest.split('.') for (num, latest_num) in zip(nums, latest_nums): if int(num) > int(latest_num): latest = version_str break if latest == '': raise Exception("Couldn't find the desired download on " + \ ' %s.' % google_code_site) return latest def run(self): """Download and install the Google Code.""" print 'Installing from %s' % self.project_name os_str = self.get_os_str version = self.find_latest_version() download_name = self.download_name_func({'os': os_str, 'version': version}) urllib.urlretrieve(self.google_code_download() + '/' + download_name, os.path.join(self.download_location, download_name)) if download_name.endswith('.zip'): z = zipfile.ZipFile(os.path.join(self.download_location, download_name)) z.extractall(self.download_location) z.close() os.remove(os.path.join(self.download_location, download_name)) @property def get_os_str(self): """The strings to indicate what OS a download is for as used on Google Code. """ os_str = 'win' if 'darwin' in sys.platform: os_str = 'mac' elif 'linux' in sys.platform: os_str = 'linux32' if '64bit' in platform.architecture()[0]: os_str = 'linux64' return os_str class FirefoxInstaller(object): """Installs the latest version of Firefox on the machine.""" def ff_download_site(self, os_name): return 'http://releases.mozilla.org/pub/mozilla.org/firefox/releases/' + \ 'latest/%s/en-US/' % os_name @property def get_os_str(self): """Returns the string that Mozilla uses to denote which operating system a Firefox binary is for.""" os_str = ('win32', '.exe') if 'darwin' in sys.platform: os_str = ('mac', '.dmg') elif 'linux' in sys.platform: os_str = ('linux-i686', '.tar.bz2') if '64bit' in platform.architecture()[0]: os_str = ('linux-x86_64', '.tar.bz2') return os_str def get_download_url(self): """Parse the html on the page to determine what is the latest download appropriate for our system.""" f = urllib2.urlopen(self.ff_download_site(self.get_os_str[0])) download_name = '' for line in f.readlines(): suffix = self.get_os_str[1] if (suffix + '"') in line: link_str = '