Merge lp:~stevanr/linaro-license-protection/production-integration-tests into lp:~linaro-automation/linaro-license-protection/trunk
- production-integration-tests
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 74 |
Proposed branch: | lp:~stevanr/linaro-license-protection/production-integration-tests |
Merge into: | lp:~linaro-automation/linaro-license-protection/trunk |
Diff against target: |
565 lines (+496/-3) 5 files modified
docs/releases.txt (+144/-0) docs/snapshots.txt (+168/-0) testing/__init__.py (+7/-1) testing/doctest_production_browser.py (+172/-0) testing/license_protected_file_downloader.py (+5/-2) |
To merge this branch: | bzr merge lp:~stevanr/linaro-license-protection/production-integration-tests |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Данило Шеган (community) | Approve | ||
Review via email: mp+105822@code.launchpad.net |
Commit message
Description of the change
Added doctest production tests for both snapshots.
New helper class for directory/file navigation.
Changes to __init to include doctest.
Данило Шеган (danilo) wrote : | # |
Данило Шеган (danilo) wrote : | # |
Uhm, make those browse_to_relative browse_to_next, mea culpa. :)
Данило Шеган (danilo) wrote : | # |
Also, I think we are missing one step. We need to confirm there is an 'accept' link in the license, and we want to simulate clicking it. I am not sure how best to do that, but I am sure you can figure something out (we can simply check if the URL there is absolute or relative, and then browse to it).
James Tunnicliffe (dooferlad) wrote : | # |
On 16 May 2012 11:34, Данило Шеган <email address hidden> wrote:
> Also, I think we are missing one step. We need to confirm there is an
> 'accept' link in the license, and we want to simulate clicking it. I am
> not sure how best to do that, but I am sure you can figure something out
> (we can simply check if the URL there is absolute or relative, and then
> browse to it).
Finding and clicking the accept link is exactly what the download
script does :-)
--
James Tunnicliffe
Данило Шеган (danilo) wrote : | # |
Right, but this is about proving that this works from a users' perspective, not that we've got code which can get through the click-through.
James Tunnicliffe (dooferlad) wrote : | # |
True, though my point was that the script emulates a user by finding
the link and following it. It may be useful in this case because it
would prove that the link exists and that clicking on it allows the
user to download the file they are expecting.
Данило Шеган (danilo) wrote : | # |
Right, understood. However, since this is supposed to be a user-readable (and repeatable) test plan, I'd rather if all the steps are clear from the actual doctest.
Stevan Radaković (stevanr) wrote : | # |
> True, though my point was that the script emulates a user by finding
> the link and following it. It may be useful in this case because it
> would prove that the link exists and that clicking on it allows the
> user to download the file they are expecting.
Imho, Danilo has the point, but James' script allows me to test this with get_protected_file method. It emulates a click to the accept license link and then gets the file requested. I'll use it in my browser class and that's it.
Данило Шеган (danilo) wrote : | # |
This looks good. It would be nice to test for 404 errors ending up on the same URL, but definitely not for this branch. At this time, this is more than good enough.
We'll probably want to decouple these tests from the automated tests since they need to run at different times (most of them before landing, these tests after deployment).
- 81. By Stevan Radaković
-
PEP8 changes.
- 82. By Stevan Radaković
-
Add new failing test for link in platform directory.
Preview Diff
1 | === added directory 'docs' |
2 | === added file 'docs/releases.txt' |
3 | --- docs/releases.txt 1970-01-01 00:00:00 +0000 |
4 | +++ docs/releases.txt 2012-05-16 16:49:24 +0000 |
5 | @@ -0,0 +1,144 @@ |
6 | +Test releases.linaro.org production server |
7 | +=========================================== |
8 | + |
9 | +Navigate to the regular ST-E license-protected file and initiate download |
10 | +------------------------------------------------------------------------- |
11 | + |
12 | +Import class we will use for this test and init browser object. |
13 | + |
14 | + >>> from testing.doctest_production_browser import DoctestProductionBrowser |
15 | + >>> browser = DoctestProductionBrowser("http://releases.linaro.org/") |
16 | + |
17 | +Visiting homepage and check for title. |
18 | + |
19 | + >>> print browser.get_content_title() |
20 | + Index of / |
21 | + |
22 | +Browsing into the latest/android/leb-snowball should work without any |
23 | +license popping out. |
24 | + |
25 | + >>> browser.browse_to_relative("latest/") |
26 | + >>> print browser.get_content_title() |
27 | + Index of /latest |
28 | + >>> browser.browse_to_relative("android/") |
29 | + >>> print browser.get_content_title() |
30 | + Index of /latest/android |
31 | + >>> browser.browse_to_relative("leb-snowball/") |
32 | + >>> print browser.get_content_title() |
33 | + Index of /latest/android/leb-snowball |
34 | + |
35 | +Mock the boot.tar.bz2 file download and check the license. |
36 | +Check if the ST-E license is encountered. |
37 | + |
38 | + >>> browser.browse_to_relative("boot.tar.bz2") |
39 | + >>> print browser.get_license_text() |
40 | + This Agreement is a legal...ST-Ericsson...GOVERNING LAW AND JURISDICTION... |
41 | + ... |
42 | + |
43 | +Now, emulate clicking on the Accept Licence link which redirects us to the |
44 | +download file. Check if the headers of the requested file are in order. |
45 | + |
46 | + >>> print browser.accept_license_get_header() |
47 | + Accept-Ranges:... |
48 | + Content-Type: application/x-bzip2... |
49 | + Location: http://releases...snowball...boot.tar.bz2... |
50 | + ... |
51 | + |
52 | +Now, emulate clicking on the Decline Licence link which redirects us to the |
53 | +decline page. |
54 | + |
55 | + >>> print browser.decline_license() |
56 | + License has not been accepted |
57 | + |
58 | + |
59 | +Navigate to the regular Samsung license-protected file and initiate download |
60 | +---------------------------------------------------------------------------- |
61 | + |
62 | +Browsing back into the /latest/android/leb-origen. It should work |
63 | +without any license popping out. |
64 | + |
65 | + >>> browser.browse_to_absolute("latest/") |
66 | + >>> print browser.get_content_title() |
67 | + Index of /latest |
68 | + >>> browser.browse_to_relative("android/") |
69 | + >>> print browser.get_content_title() |
70 | + Index of /latest/android |
71 | + >>> browser.browse_to_relative("leb-origen/") |
72 | + >>> print browser.get_content_title() |
73 | + Index of /latest/android/leb-origen |
74 | + |
75 | +Mock the boot.tar.bz2 file download and check the license. |
76 | +Check if the Samsung license is encountered. |
77 | + |
78 | + >>> browser.browse_to_relative("boot.tar.bz2") |
79 | + >>> print browser.get_license_text() |
80 | + IMPORTANT...SAMSUNG ELECTRONICS...Entire Agreement... |
81 | + ... |
82 | + |
83 | +Now, emulate clicking on the Accept Licence link which redirects us to the |
84 | +download file. Check if the headers of the requested file are in order. |
85 | + |
86 | + >>> print browser.accept_license_get_header() |
87 | + Accept-Ranges:... |
88 | + Content-Type: application/x-bzip2... |
89 | + Location: http://releases...origen...boot.tar.bz2... |
90 | + ... |
91 | + |
92 | +Now, emulate clicking on the Decline Licence link which redirects us to the |
93 | +decline page. |
94 | + |
95 | + >>> print browser.decline_license() |
96 | + License has not been accepted |
97 | + |
98 | + |
99 | +Navigate to the non-license-protected file and initiate download |
100 | +---------------------------------------------------------------- |
101 | + |
102 | +Browsing back into the latest/android/leb-panda. It should work |
103 | +without any license popping out. |
104 | + |
105 | + >>> browser.browse_to_absolute("latest/") |
106 | + >>> print browser.get_content_title() |
107 | + Index of /latest |
108 | + >>> browser.browse_to_relative("android/") |
109 | + >>> print browser.get_content_title() |
110 | + Index of /latest/android |
111 | + >>> browser.browse_to_relative("leb-panda/") |
112 | + >>> print browser.get_content_title() |
113 | + Index of /latest/android/leb-panda |
114 | + |
115 | +Mock the boot.tar.bz2 file download. There should not be any |
116 | +license encountered. |
117 | + |
118 | + >>> browser.browse_to_relative("boot.tar.bz2") |
119 | + >>> print browser.get_unprotected_file_header() |
120 | + Accept-Ranges:... |
121 | + Content-Type: application/x-bzip2... |
122 | + ... |
123 | + |
124 | + |
125 | +Try accessing the leb-snowball link in platform latest android dir |
126 | +------------------------------------------------------------------ |
127 | + |
128 | +Browsing back into the platform/latest/android/latest. It should work |
129 | +without any license popping out. |
130 | + |
131 | + >>> browser.browse_to_absolute("platform/") |
132 | + >>> print browser.get_content_title() |
133 | + Index of /platform |
134 | + >>> browser.browse_to_relative("latest/") |
135 | + >>> print browser.get_content_title() |
136 | + Index of /platform/latest |
137 | + >>> browser.browse_to_relative("android/") |
138 | + >>> print browser.get_content_title() |
139 | + Index of /platform/latest/android |
140 | + >>> browser.browse_to_relative("latest/") |
141 | + >>> print browser.get_content_title() |
142 | + Index of /platform/latest/android/latest |
143 | + |
144 | + |
145 | +Now try opening the leb-snowball link. |
146 | + |
147 | + >>> browser.browse_to_relative("leb-snowball/") |
148 | + >>> print browser.get_content_title() |
149 | + Index of /platform/latest/android/latest/leb-snowball |
150 | |
151 | === added file 'docs/snapshots.txt' |
152 | --- docs/snapshots.txt 1970-01-01 00:00:00 +0000 |
153 | +++ docs/snapshots.txt 2012-05-16 16:49:24 +0000 |
154 | @@ -0,0 +1,168 @@ |
155 | +Test snapshots.linaro.org production server |
156 | +=========================================== |
157 | + |
158 | +Navigate to the regular ST-E license-protected file and initiate download |
159 | +------------------------------------------------------------------------- |
160 | + |
161 | +Import class we will use for this test and init browser object. |
162 | + |
163 | + >>> from testing.doctest_production_browser import DoctestProductionBrowser |
164 | + >>> browser = DoctestProductionBrowser("http://snapshots.linaro.org/") |
165 | + |
166 | +Visiting homepage and check for title. |
167 | + |
168 | + >>> print browser.get_content_title() |
169 | + Index of / |
170 | + |
171 | +Browsing into the android/~linaro-android/*snowball* should work without any |
172 | +license popping out. |
173 | + |
174 | + >>> browser.browse_to_relative("android/") |
175 | + >>> print browser.get_content_title() |
176 | + Index of /android |
177 | + >>> browser.browse_to_relative("~linaro-android/") |
178 | + >>> print browser.get_content_title() |
179 | + Index of /android/~linaro-android |
180 | + >>> browser.browse_to_next("snowball") |
181 | + >>> print browser.get_content_title() |
182 | + Index of /android/~linaro-android/...snowball... |
183 | + |
184 | +Go to build number page. We don't know which are the build numbers so we |
185 | +will visit the first directory link available. Next, go to target, then product |
186 | +then snowball links, respectively. |
187 | + |
188 | + >>> browser.browse_to_next("") |
189 | + >>> print browser.get_content_title() |
190 | + Index of /android/~linaro-android/...snowball... |
191 | + >>> browser.browse_to_relative("target/") |
192 | + >>> print browser.get_content_title() |
193 | + Index of /android/~linaro-android/...snowball...target |
194 | + >>> browser.browse_to_relative("product/") |
195 | + >>> print browser.get_content_title() |
196 | + Index of /android/~linaro-android/...snowball...target...product... |
197 | + >>> browser.browse_to_relative("snowball/") |
198 | + >>> print browser.get_content_title() |
199 | + Index of /android/~linaro-android/...snowball...product...snowball... |
200 | + |
201 | +Finally, mock the boot.tar.bz2 file download and check the license. |
202 | +Check if the ST-E license is encountered. |
203 | + |
204 | + >>> browser.browse_to_relative("boot.tar.bz2") |
205 | + >>> print browser.get_license_text() |
206 | + This Agreement is a legal...ST-Ericsson...GOVERNING LAW AND JURISDICTION... |
207 | + ... |
208 | + |
209 | +Now, emulate clicking on the Accept Licence link which redirects us to the |
210 | +download file. Check if the headers of the requested file are in order. |
211 | + |
212 | + >>> print browser.accept_license_get_header() |
213 | + Accept-Ranges:... |
214 | + Content-Type: application/x-bzip2... |
215 | + Location: http://snapshots...snowball...boot.tar.bz2... |
216 | + ... |
217 | + |
218 | +Now, emulate clicking on the Decline Licence link which redirects us to the |
219 | +decline page. |
220 | + |
221 | + >>> print browser.decline_license() |
222 | + License has not been accepted |
223 | + |
224 | + |
225 | +Navigate to the regular Samsung license-protected file and initiate download |
226 | +---------------------------------------------------------------------------- |
227 | + |
228 | +Browsing back into the android/~linaro-android/*origen*. It should work |
229 | +without any license popping out. |
230 | + |
231 | + >>> browser.browse_to_absolute("android/") |
232 | + >>> print browser.get_content_title() |
233 | + Index of /android |
234 | + >>> browser.browse_to_relative("~linaro-android/") |
235 | + >>> print browser.get_content_title() |
236 | + Index of /android/~linaro-android |
237 | + >>> browser.browse_to_next("origen") |
238 | + >>> print browser.get_content_title() |
239 | + Index of /android/~linaro-android/...origen... |
240 | + |
241 | +Go to build number page. We don't know which are the build numbers so we |
242 | +will visit the first directory link available. Next, go to target, then product |
243 | +then origen links, respectively. |
244 | + |
245 | + >>> browser.browse_to_next("") |
246 | + >>> print browser.get_content_title() |
247 | + Index of /android/~linaro-android/...origen... |
248 | + >>> browser.browse_to_relative("target/") |
249 | + >>> print browser.get_content_title() |
250 | + Index of /android/~linaro-android/...origen...target |
251 | + >>> browser.browse_to_relative("product/") |
252 | + >>> print browser.get_content_title() |
253 | + Index of /android/~linaro-android/...origen...target...product... |
254 | + >>> browser.browse_to_relative("origen/") |
255 | + >>> print browser.get_content_title() |
256 | + Index of /android/~linaro-android/...origen...product...origen... |
257 | + |
258 | +Finally, mock the boot.tar.bz2 file download and check the license. |
259 | +Check if the Samsung license is encountered. |
260 | + |
261 | + >>> browser.browse_to_relative("boot.tar.bz2") |
262 | + >>> print browser.get_license_text() |
263 | + IMPORTANT...SAMSUNG ELECTRONICS...Entire Agreement... |
264 | + ... |
265 | + |
266 | +Now, emulate clicking on the Accept Licence link which redirects us to the |
267 | +download file. Check if the headers of the requested file are in order. |
268 | + |
269 | + >>> print browser.accept_license_get_header() |
270 | + Accept-Ranges:... |
271 | + Content-Type: application/x-bzip2... |
272 | + Location: http://snapshots...origen...boot.tar.bz2... |
273 | + ... |
274 | + |
275 | +Now, emulate clicking on the Decline Licence link which redirects us to the |
276 | +decline page. |
277 | + |
278 | + >>> print browser.decline_license() |
279 | + License has not been accepted |
280 | + |
281 | + |
282 | +Navigate to the non-license-protected file and initiate download |
283 | +---------------------------------------------------------------- |
284 | + |
285 | +Browsing back into the android/~linaro-android/*panda*. It should work |
286 | +without any license popping out. |
287 | + |
288 | + >>> browser.browse_to_absolute("android/") |
289 | + >>> print browser.get_content_title() |
290 | + Index of /android |
291 | + >>> browser.browse_to_relative("~linaro-android/") |
292 | + >>> print browser.get_content_title() |
293 | + Index of /android/~linaro-android |
294 | + >>> browser.browse_to_next("panda") |
295 | + >>> print browser.get_content_title() |
296 | + Index of /android/~linaro-android/...panda... |
297 | + |
298 | +Go to build number page. We don't know which are the build numbers so we |
299 | +will visit the first directory link available. Next, go to target, then product |
300 | +then pandaboard links, respectively. |
301 | + |
302 | + >>> browser.browse_to_next("") |
303 | + >>> print browser.get_content_title() |
304 | + Index of /android/~linaro-android/...panda... |
305 | + >>> browser.browse_to_relative("target/") |
306 | + >>> print browser.get_content_title() |
307 | + Index of /android/~linaro-android/...panda...target |
308 | + >>> browser.browse_to_relative("product/") |
309 | + >>> print browser.get_content_title() |
310 | + Index of /android/~linaro-android/...panda...target...product... |
311 | + >>> browser.browse_to_next("panda") |
312 | + >>> print browser.get_content_title() |
313 | + Index of /android/~linaro-android/...panda...product...panda... |
314 | + |
315 | +Finally, mock the boot.tar.bz2 file download. There should not be any |
316 | +license encountered. |
317 | + |
318 | + >>> browser.browse_to_relative("boot.tar.bz2") |
319 | + >>> print browser.get_unprotected_file_header() |
320 | + Accept-Ranges:... |
321 | + Content-Type: application/x-bzip2... |
322 | + ... |
323 | |
324 | === modified file 'testing/__init__.py' |
325 | --- testing/__init__.py 2012-05-11 14:02:26 +0000 |
326 | +++ testing/__init__.py 2012-05-16 16:49:24 +0000 |
327 | @@ -1,9 +1,11 @@ |
328 | import os |
329 | import unittest |
330 | +import doctest |
331 | |
332 | from testing.test_click_through_license import * |
333 | from testing.test_publish_to_snapshots import * |
334 | |
335 | + |
336 | def test_suite(): |
337 | module_names = [ |
338 | 'testing.test_click_through_license.TestLicense', |
339 | @@ -12,5 +14,9 @@ |
340 | ] |
341 | loader = unittest.TestLoader() |
342 | suite = loader.loadTestsFromNames(module_names) |
343 | + for filename in os.listdir("docs/"): |
344 | + suite.addTest(doctest.DocFileSuite( |
345 | + 'docs/' + filename, module_relative=False, |
346 | + optionflags=doctest.ELLIPSIS) |
347 | + ) |
348 | return suite |
349 | - |
350 | |
351 | === added file 'testing/doctest_production_browser.py' |
352 | --- testing/doctest_production_browser.py 1970-01-01 00:00:00 +0000 |
353 | +++ testing/doctest_production_browser.py 2012-05-16 16:49:24 +0000 |
354 | @@ -0,0 +1,172 @@ |
355 | +from BeautifulSoup import BeautifulSoup |
356 | + |
357 | +from license_protected_file_downloader import LicenseProtectedFileFetcher |
358 | + |
359 | + |
360 | +class EmptyDirectoryException(Exception): |
361 | + ''' Directory at the current URL is empty. ''' |
362 | + |
363 | + |
364 | +class NoLicenseException(Exception): |
365 | + ''' No license protecting the file. ''' |
366 | + |
367 | + |
368 | +class UnexpectedLicenseException(Exception): |
369 | + ''' License protecting non-licensed the file. ''' |
370 | + |
371 | + |
372 | +class DoctestProductionBrowser(): |
373 | + """Doctest production testing browser class.""" |
374 | + |
375 | + def __init__(self, host_address): |
376 | + self.host_address = host_address |
377 | + self.current_url = host_address |
378 | + self.fetcher = LicenseProtectedFileFetcher() |
379 | + |
380 | + def is_dir(self, link): |
381 | + """Check if the link is a directory.""" |
382 | + return link[-1] == "/" |
383 | + |
384 | + def get_header(self): |
385 | + """Get header from the current url.""" |
386 | + return self.parse_header(self.fetcher.get_headers(self.current_url)) |
387 | + |
388 | + def get_license_text(self): |
389 | + """Get license from the current URL if it redirects to license.""" |
390 | + license = self.fetcher.get_or_return_license(self.current_url) |
391 | + if license[0]: |
392 | + return license[0] |
393 | + else: |
394 | + raise NoLicenseException("License expected here.") |
395 | + |
396 | + def get_unprotected_file_header(self): |
397 | + """Get headers from unprotected file.""" |
398 | + page = self.fetcher.get_or_return_license(self.current_url) |
399 | + # Check if license with accept and decline links is returned. |
400 | + if len(page) == 3: |
401 | + raise UnexpectedLicenseException("License not expected here.") |
402 | + else: |
403 | + return self.parse_header(self.fetcher.header) |
404 | + |
405 | + def get_content(self): |
406 | + """Get contents from the current url.""" |
407 | + return self.fetcher.get(self.current_url) |
408 | + |
409 | + def get_content_title(self): |
410 | + """Get content title from the current url.""" |
411 | + return self.get_title(self.fetcher.get(self.current_url)) |
412 | + |
413 | + def get_header_when_redirected(self): |
414 | + """Get header when the client is redirected to the license.""" |
415 | + self.fetcher.get(self.current_url) |
416 | + return self.parse_header(self.fetcher.header) |
417 | + |
418 | + def accept_license_get_header(self): |
419 | + """Accept license and get header of the file it redirects to.""" |
420 | + license = self.fetcher.get_or_return_license(self.current_url) |
421 | + # Second element in result is the accept link. |
422 | + if license[1]: |
423 | + self.fetcher.get_protected_file(license[1], self.current_url) |
424 | + return self.parse_header(self.fetcher.header) |
425 | + else: |
426 | + raise NoLicenseException("License expected here.") |
427 | + |
428 | + def decline_license(self): |
429 | + """Decline license. Return title of the page.""" |
430 | + return self.get_title( |
431 | + self.fetcher.get(self.current_url, accept_license=False) |
432 | + ) |
433 | + |
434 | + def parse_header(self, header): |
435 | + """Formats headers from dict form to the multi-line string.""" |
436 | + header_str = "" |
437 | + for key in sorted(header.iterkeys()): |
438 | + header_str += "%s: %s\n" % (key, header[key]) |
439 | + return header_str |
440 | + |
441 | + def get_title(self, html): |
442 | + soup = BeautifulSoup(html) |
443 | + titles_all = soup.findAll('title') |
444 | + if len(titles_all) > 0: |
445 | + return titles_all[0].contents[0] |
446 | + else: |
447 | + return "" |
448 | + |
449 | + def browse_to_relative(self, path): |
450 | + """Change current url relatively.""" |
451 | + self.current_url += path |
452 | + |
453 | + def browse_to_absolute(self, path): |
454 | + """Change current url to specified path.""" |
455 | + self.current_url = self.host_address + path |
456 | + |
457 | + def browse_to_next(self, condition): |
458 | + """Browse to next dir/build file that matches condition. |
459 | + |
460 | + Set the current URL to to match the condition among the |
461 | + links in the current page with priority to build files. |
462 | + If there's no match, set link to build file if present. |
463 | + Otherwise, set link to first directory present. |
464 | + """ |
465 | + links = self.find_links(self.get_content()) |
466 | + link = self.find_link_with_condition(links, condition) |
467 | + if not link: |
468 | + # No link matching condition, get first build in list. |
469 | + link = self.find_build_tar_bz2(links) |
470 | + if not link: |
471 | + # Still no link, just get first dir in list. |
472 | + link = self.find_directory(links) |
473 | + if not link: |
474 | + # We found page with no directories nor builds. |
475 | + raise EmptyDirectoryException("Directory is empty.") |
476 | + |
477 | + self.browse_to_relative(link) |
478 | + |
479 | + def find_links(self, html): |
480 | + """Return list of links on the page with special conditions. |
481 | + |
482 | + Return all links below the "Parent directory" link. |
483 | + Return whole list if there is no such link. |
484 | + """ |
485 | + soup = BeautifulSoup(html) |
486 | + links_all = soup.findAll('a') |
487 | + had_parent = False |
488 | + links = [] |
489 | + for link in links_all: |
490 | + if had_parent: |
491 | + links.append(link.get("href")) |
492 | + if link.contents[0] == "Parent Directory": |
493 | + had_parent = True |
494 | + |
495 | + if had_parent: |
496 | + return links |
497 | + else: |
498 | + return [each.get('href') for each in links_all] |
499 | + |
500 | + def find_link_with_condition(self, links, condition): |
501 | + """Finds a link which satisfies the condition. |
502 | + |
503 | + Condition is actually to contain the string from the list. |
504 | + Build files (which end in .tar.bz2) have the priority. |
505 | + """ |
506 | + for link in links: |
507 | + if condition in link and link[-7:] == "tar.bz2": |
508 | + return link |
509 | + for link in links: |
510 | + if condition in link: |
511 | + return link |
512 | + return None |
513 | + |
514 | + def find_directory(self, links): |
515 | + """Finds a directory among list of links.""" |
516 | + for link in links: |
517 | + if self.is_dir(link): |
518 | + return link |
519 | + return None |
520 | + |
521 | + def find_build_tar_bz2(self, links): |
522 | + """Finds a file list of links which ends in tar.bz2.""" |
523 | + for link in links: |
524 | + if link[-7:] == "tar.bz2": |
525 | + return link |
526 | + return None |
527 | |
528 | === modified file 'testing/license_protected_file_downloader.py' |
529 | --- testing/license_protected_file_downloader.py 2012-05-11 08:32:52 +0000 |
530 | +++ testing/license_protected_file_downloader.py 2012-05-16 16:49:24 +0000 |
531 | @@ -8,6 +8,7 @@ |
532 | import html2text |
533 | from BeautifulSoup import BeautifulSoup |
534 | |
535 | + |
536 | class LicenseProtectedFileFetcher: |
537 | """Fetch a file from the web that may be protected by a license redirect |
538 | |
539 | @@ -124,7 +125,8 @@ |
540 | |
541 | return self.body |
542 | |
543 | - def get(self, url, file_name=None, ignore_license=False, accept_license=True): |
544 | + def get(self, url, file_name=None, ignore_license=False, |
545 | + accept_license=True): |
546 | """Fetch the requested URL, accepting licenses |
547 | |
548 | Fetches the file at url. If a redirect is encountered, it is |
549 | @@ -241,7 +243,7 @@ |
550 | |
551 | # Only buffer first 1MB of body. This should be plenty for anything |
552 | # we wish to parse internally. |
553 | - if len(self.body) < 1024*1024*1024: |
554 | + if len(self.body) < 1024 * 1024 * 1024: |
555 | # XXX Would be nice to stop keeping the file in RAM at all and |
556 | # passing large buffers around. Perhaps only keep in RAM if |
557 | # file_name == None? (used for getting directory listings |
558 | @@ -260,6 +262,7 @@ |
559 | """Wrapper to close curl - this will allow curl to write out cookies""" |
560 | self.curl.close() |
561 | |
562 | + |
563 | def main(): |
564 | """Download file specified on command line""" |
565 | parser = argparse.ArgumentParser(description="Download a file, accepting " |
So much nicer, thanks for working on this.
Now, considering what is mostly tested, I'd suggest you add a get_content_title() method which extracts the title tag (considering you are already using BeautifulSoup, that should be easy), so the output would be nicer and even more clear, for example:
Browsing into the android/ ~linaro- android/ *snowball* works without asking for any license acceptance:
>>> browser. browse_ to_relative( "android/ ") get_content_ title() browse_ to_relative( "~linaro- android" ) get_content_ title() ~linaro- android' browse_ to_relative( "snowball" ) get_content_ title() ~linaro- android/ ...snowball. ..'
>>> browser.
u'Index of /android'
>>> browser.
>>> browser.
u'Index of /android/
>>> browser.
>>> browser.
u'Index of /android/
As you can see, I am also suggesting joining a few steps behind a single narrative. I'd suggest you do the same for the target/product/* step as well.
I like all the other improvements (DoctestProduct ionBrowser( host), get_license() call etc).
It would still be nicer to print out the headers one-per-line instead of as a dict:
>>> print browser. get_header_ when_redirected ()
Content- Length: ... snapshots. ../boot. tar.bz2
Content- Type: application/x-bzip2
Location: http://
...
Also note that there is no guarantee in what order headers will be returned, and this test might easily break, so I suggest get_headers_ when_redirected sorts them by name before returning a string with one header per line.