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 |