Merge lp:~cjwatson/launchpad/beautifulsoup-no-deprecated into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 18506
Proposed branch: lp:~cjwatson/launchpad/beautifulsoup-no-deprecated
Merge into: lp:launchpad
Prerequisite: lp:~cjwatson/launchpad/beautifulsoup-wrapper
Diff against target: 1338 lines (+166/-166)
37 files modified
lib/lp/answers/stories/faq-browse-and-search.txt (+1/-1)
lib/lp/answers/stories/project-add-question.txt (+4/-4)
lib/lp/answers/stories/question-add-in-other-languages.txt (+1/-1)
lib/lp/answers/stories/question-browse-and-search.txt (+49/-49)
lib/lp/answers/stories/question-edit.txt (+2/-2)
lib/lp/answers/stories/question-overview.txt (+3/-3)
lib/lp/answers/stories/question-search-multiple-languages.txt (+16/-16)
lib/lp/answers/stories/question-workflow.txt (+15/-15)
lib/lp/answers/stories/questions-index.txt (+6/-6)
lib/lp/blueprints/stories/blueprints/xx-buglinks.txt (+2/-2)
lib/lp/blueprints/stories/sprints/xx-sprints.txt (+1/-1)
lib/lp/blueprints/stories/standalone/subscribing.txt (+3/-3)
lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt (+2/-2)
lib/lp/bugs/stories/bugs/xx-bug-single-comment-view.txt (+1/-1)
lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt (+2/-2)
lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt (+1/-1)
lib/lp/bugs/stories/cve/cve-linking.txt (+1/-1)
lib/lp/bugs/tests/bug.py (+1/-1)
lib/lp/code/stories/branches/xx-bazaar-home.txt (+7/-7)
lib/lp/code/stories/branches/xx-branch-listings-merge-proposal-badge.txt (+2/-2)
lib/lp/code/stories/branches/xx-branch-listings.txt (+19/-19)
lib/lp/code/stories/branches/xx-branch-tag-cloud.txt (+1/-1)
lib/lp/code/stories/branches/xx-person-branches.txt (+3/-3)
lib/lp/code/stories/branches/xx-private-branch-listings.txt (+3/-3)
lib/lp/code/stories/branches/xx-product-branches.txt (+4/-4)
lib/lp/code/stories/branches/xx-product-overview.txt (+1/-1)
lib/lp/code/stories/branches/xx-project-branches.txt (+1/-1)
lib/lp/code/stories/branches/xx-source-package-branches-listing.txt (+1/-1)
lib/lp/code/stories/branches/xx-subscribing-branches.txt (+1/-1)
lib/lp/code/stories/codeimport/xx-codeimport-results.txt (+2/-2)
lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt (+2/-2)
lib/lp/coop/answersbugs/stories/question-buglink.txt (+2/-2)
lib/lp/coop/answersbugs/stories/question-makebug.txt (+1/-1)
lib/lp/soyuz/stories/ppa/xx-private-ppa-presentation.txt (+2/-2)
lib/lp/translations/stories/standalone/xx-person-editlanguages.txt (+1/-1)
lib/lp/translations/stories/standalone/xx-pofile-export.txt (+1/-1)
lib/lp/translations/stories/translationgroups/xx-translationgroups.txt (+1/-1)
To merge this branch: bzr merge lp:~cjwatson/launchpad/beautifulsoup-no-deprecated
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+332601@code.launchpad.net

Commit message

Stop using pre-3.x BeautifulSoup compatibility methods.

Description of the change

These are understandably entirely gone in 4.x.

This is long, but it's totally formulaic and test-only. .fetch() becomes .findAll() (which unfortunately gets renamed again in 4.x to .find_all(), but at least there's a compatibility method in place), .first() becomes .find(), and .firstText(text) becomes .find(text=text). The only care needed was to avoid touching non-BeautifulSoup uses of those method names.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/answers/stories/faq-browse-and-search.txt'
2--- lib/lp/answers/stories/faq-browse-and-search.txt 2011-12-23 23:44:59 +0000
3+++ lib/lp/answers/stories/faq-browse-and-search.txt 2017-10-23 00:36:01 +0000
4@@ -138,7 +138,7 @@
5
6 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
7 >>> for question in questions.findAll('td', 'questionTITLE'):
8- ... print question.first('a').renderContents()
9+ ... print question.find('a').renderContents()
10 Installation of Java Runtime Environment for Mozilla
11
12 On the question page, there is also a link to consult the FAQs matching
13
14=== modified file 'lib/lp/answers/stories/project-add-question.txt'
15--- lib/lp/answers/stories/project-add-question.txt 2016-01-26 15:47:37 +0000
16+++ lib/lp/answers/stories/project-add-question.txt 2017-10-23 00:36:01 +0000
17@@ -72,7 +72,7 @@
18
19 >>> similar_questions = find_tag_by_id(
20 ... user_browser.contents, 'similar-questions')
21- >>> for row in similar_questions.fetch('li'):
22+ >>> for row in similar_questions.findAll('li'):
23 ... print row.a.renderContents()
24 2: Problem showing the SVG demo on W3C site
25
26@@ -93,7 +93,7 @@
27 missing:
28
29 >>> soup = find_main_content(user_browser.contents)
30- >>> print soup.first('div', 'message').renderContents()
31+ >>> print soup.find('div', 'message').renderContents()
32 You must enter a summary of your problem.
33
34 The product Thunderbird that they selected on the previous screen is still
35@@ -112,7 +112,7 @@
36 an appropriate message is displayed to inform them of this:
37
38 >>> soup = find_main_content(user_browser.contents)
39- >>> print soup.first('p').renderContents()
40+ >>> print soup.find('p').renderContents()
41 There are no existing FAQs or questions similar to the summary you
42 entered.
43
44@@ -188,7 +188,7 @@
45 >>> user_browser.getControl('Japanese').selected = True
46 >>> user_browser.getControl('Save').click()
47 >>> soup = find_main_content(user_browser.contents)
48- >>> print soup.first('div', 'informational message').renderContents()
49+ >>> print soup.find('div', 'informational message').renderContents()
50 Added Japanese to your preferred languages.
51
52 So if No Privileges Person were to visit the Ask a Question page for
53
54=== modified file 'lib/lp/answers/stories/question-add-in-other-languages.txt'
55--- lib/lp/answers/stories/question-add-in-other-languages.txt 2016-01-26 15:47:37 +0000
56+++ lib/lp/answers/stories/question-add-in-other-languages.txt 2017-10-23 00:36:01 +0000
57@@ -50,7 +50,7 @@
58 already finds nothing.
59
60 #>>> for row in similar_questions.findAll('tr', 'noted'):
61- #... row.first('a').renderContents()
62+ #... row.find('a').renderContents()
63 #'Installation of Java Runtime Environment for Mozilla'
64 #'Problema al recompilar kernel con soporte smp (doble-n\xc3\xbacleo)'
65
66
67=== modified file 'lib/lp/answers/stories/question-browse-and-search.txt'
68--- lib/lp/answers/stories/question-browse-and-search.txt 2016-01-26 15:47:37 +0000
69+++ lib/lp/answers/stories/question-browse-and-search.txt 2017-10-23 00:36:01 +0000
70@@ -29,7 +29,7 @@
71 >>> print browser.title
72 Questions : Kubuntu
73
74- >>> print find_main_content(browser.contents).first('p').renderContents()
75+ >>> print find_main_content(browser.contents).find('p').renderContents()
76 There are no questions for Kubuntu with the requested statuses.
77
78 For projects that don't have products, the Answers facet is disabled.
79@@ -52,8 +52,8 @@
80 He sees a listing of the current questions posted on Ubuntu:
81
82 >>> soup = find_main_content(browser.contents)
83- >>> for question in soup.fetch('td', 'questionTITLE'):
84- ... print question.first('a').renderContents()
85+ >>> for question in soup.findAll('td', 'questionTITLE'):
86+ ... print question.find('a').renderContents()
87 Continue playing after shutdown
88 Play DVDs in Totem
89 mailto: problem in webpage
90@@ -68,8 +68,8 @@
91 >>> print browser.title
92 Questions : Ubuntu
93 >>> soup = find_main_content(browser.contents)
94- >>> for question in soup.fetch('td', 'questionTITLE'):
95- ... print question.first('a').renderContents()
96+ >>> for question in soup.findAll('td', 'questionTITLE'):
97+ ... print question.find('a').renderContents()
98 Installation failed
99
100 This is the last results page, so the next and last links are greyed
101@@ -114,11 +114,11 @@
102
103 >>> import re
104 >>> soup = find_main_content(browser.contents)
105- >>> question_link = soup.first('a', text=re.compile('Play DVDs'))
106+ >>> question_link = soup.find('a', text=re.compile('Play DVDs'))
107 >>> print question_link.findParent('tr')['title']
108 How do you play DVDs in Totem..........?
109
110- >>> question_link = soup.first('a', text=re.compile('Slow system'))
111+ >>> question_link = soup.find('a', text=re.compile('Slow system'))
112 >>> print question_link.findParent('tr')['title']
113 I get really poor hard drive performance.
114
115@@ -174,7 +174,7 @@
116 >>> print browser.title
117 Questions matching "question 8"
118
119- >>> print find_main_content(browser.contents).first('p').renderContents()
120+ >>> print find_main_content(browser.contents).find('p').renderContents()
121 There are no questions matching "question 8" with the requested statuses.
122
123
124@@ -219,8 +219,8 @@
125 This time, the search returns one item.
126
127 >>> soup = find_main_content(browser.contents)
128- >>> for question in soup.fetch('td', 'questionTITLE'):
129- ... print question.first('a').renderContents()
130+ >>> for question in soup.findAll('td', 'questionTITLE'):
131+ ... print question.find('a').renderContents()
132 Firefox is slow and consumes too much RAM
133
134 He clicks on the link to read the question description.
135@@ -294,8 +294,8 @@
136 >>> print browser.title
137 Questions : Mozilla Firefox
138 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
139- >>> for question in questions.fetch('td', 'questionTITLE'):
140- ... print question.first('a').renderContents()
141+ >>> for question in questions.findAll('td', 'questionTITLE'):
142+ ... print question.find('a').renderContents()
143 Firefox loses focus and gets stuck
144 Problem showing the SVG demo on W3C site
145 Firefox cannot render Bank Site
146@@ -314,8 +314,8 @@
147 >>> browser.getControl(name='field.search_text').value = 'plugin'
148 >>> browser.getControl('Search', index=0).click()
149 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
150- >>> for question in questions.fetch('td', 'questionTITLE'):
151- ... print question.first('a').renderContents()
152+ >>> for question in questions.findAll('td', 'questionTITLE'):
153+ ... print question.find('a').renderContents()
154 Problem showing the SVG demo on W3C site
155
156
157@@ -334,8 +334,8 @@
158 >>> [strip_label(status) for status in statuses]
159 ['Answered', 'Solved']
160 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
161- >>> for question in questions.fetch('td', 'questionTITLE'):
162- ... print question.first('a').renderContents()
163+ >>> for question in questions.findAll('td', 'questionTITLE'):
164+ ... print question.find('a').renderContents()
165 Play DVDs in Totem
166 mailto: problem in webpage
167 Installation of Java Runtime Environment for Mozilla
168@@ -379,8 +379,8 @@
169 'Questions you asked about mozilla-firefox in Ubuntu : Questions : mozilla-firefox package : Ubuntu'
170 >>> questions = find_tag_by_id(
171 ... sample_person_browser.contents, 'question-listing')
172- >>> for question in questions.fetch('td', 'questionTITLE'):
173- ... print question.first('a').renderContents()
174+ >>> for question in questions.findAll('td', 'questionTITLE'):
175+ ... print question.find('a').renderContents()
176 mailto: problem in webpage
177 Installation of Java Runtime Environment for Mozilla
178
179@@ -401,8 +401,8 @@
180
181 >>> questions = find_tag_by_id(
182 ... sample_person_browser.contents, 'question-listing')
183- >>> for question in questions.fetch('td', 'questionTITLE'):
184- ... print question.first('a').renderContents()
185+ >>> for question in questions.findAll('td', 'questionTITLE'):
186+ ... print question.find('a').renderContents()
187 mailto: problem in webpage
188
189 If the user didn't make any questions on the product, a message
190@@ -420,7 +420,7 @@
191 ... 'http://launchpad.dev/gnomebaker/+questions')
192 >>> sample_person_browser.getLink('My questions').click()
193 >>> print find_main_content(
194- ... sample_person_browser.contents).first('p').renderContents()
195+ ... sample_person_browser.contents).find('p').renderContents()
196 You didn't ask any questions about gnomebaker.
197
198
199@@ -447,8 +447,8 @@
200 Questions needing your attention for Ubuntu : Questions : Ubuntu
201 >>> questions = find_tag_by_id(
202 ... sample_person_browser.contents, 'question-listing')
203- >>> for question in questions.fetch('td', 'questionTITLE'):
204- ... print question.first('a').renderContents()
205+ >>> for question in questions.findAll('td', 'questionTITLE'):
206+ ... print question.find('a').renderContents()
207 Play DVDs in Totem
208 Installation of Java Runtime Environment for Mozilla
209
210@@ -472,7 +472,7 @@
211 ... 'http://launchpad.dev/products/gnomebaker/+questions')
212 >>> sample_person_browser.getLink('Need attention').click()
213 >>> print find_main_content(
214- ... sample_person_browser.contents).first('p').renderContents()
215+ ... sample_person_browser.contents).find('p').renderContents()
216 No questions need your attention for gnomebaker.
217
218
219@@ -492,8 +492,8 @@
220 Questions : Foo Bar
221
222 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
223- >>> for question in questions.fetch('td', 'questionTITLE'):
224- ... print question.first('a').renderContents()
225+ >>> for question in questions.findAll('td', 'questionTITLE'):
226+ ... print question.find('a').renderContents()
227 Continue playing after shutdown
228 Play DVDs in Totem
229 mailto: problem in webpage
230@@ -508,8 +508,8 @@
231 The listing contains a 'In' column that shows the context where the
232 questions was made.
233
234- >>> for question in questions.fetch('td', 'question-target'):
235- ... print question.first('a').renderContents()
236+ >>> for question in questions.findAll('td', 'question-target'):
237+ ... print question.find('a').renderContents()
238 Ubuntu
239 Ubuntu
240 mozilla-firefox in Ubuntu
241@@ -532,8 +532,8 @@
242 ... 'Solved', 'Invalid']
243 >>> browser.getControl('Search', index=0).click()
244 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
245- >>> for question in questions.fetch('td', 'questionTITLE'):
246- ... print question.first('a').renderContents()
247+ >>> for question in questions.findAll('td', 'questionTITLE'):
248+ ... print question.find('a').renderContents()
249 Firefox is slow and consumes too much RAM
250 mailto: problem in webpage
251
252@@ -549,7 +549,7 @@
253 >>> browser.getLink('Assigned').click()
254 >>> print browser.title
255 Questions for Foo Bar : Questions : Foo Bar
256- >>> print find_main_content(browser.contents).first('p').renderContents()
257+ >>> print find_main_content(browser.contents).find('p').renderContents()
258 No questions assigned to Foo Bar found with the requested statuses.
259
260
261@@ -562,8 +562,8 @@
262 >>> print browser.title
263 Questions for Foo Bar : Questions : Foo Bar
264 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
265- >>> for question in questions.fetch('td', 'questionTITLE'):
266- ... print question.first('a').renderContents()
267+ >>> for question in questions.findAll('td', 'questionTITLE'):
268+ ... print question.find('a').renderContents()
269 mailto: problem in webpage
270
271
272@@ -576,8 +576,8 @@
273 >>> print browser.title
274 Questions for Foo Bar : Questions : Foo Bar
275 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
276- >>> for question in questions.fetch('td', 'questionTITLE'):
277- ... print question.first('a').renderContents()
278+ >>> for question in questions.findAll('td', 'questionTITLE'):
279+ ... print question.find('a').renderContents()
280 Continue playing after shutdown
281 Play DVDs in Totem
282 mailto: problem in webpage
283@@ -594,8 +594,8 @@
284 >>> print browser.title
285 Questions for Foo Bar : Questions : Foo Bar
286 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
287- >>> for question in questions.fetch('td', 'questionTITLE'):
288- ... print question.first('a').renderContents()
289+ >>> for question in questions.findAll('td', 'questionTITLE'):
290+ ... print question.find('a').renderContents()
291 Slow system
292 Firefox loses focus and gets stuck
293
294@@ -609,8 +609,8 @@
295 >>> print browser.title
296 Questions for Foo Bar : Questions : Foo Bar
297 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
298- >>> for question in questions.fetch('td', 'questionTITLE'):
299- ... print question.first('a').renderContents()
300+ >>> for question in questions.findAll('td', 'questionTITLE'):
301+ ... print question.find('a').renderContents()
302 Continue playing after shutdown
303 Slow system
304
305@@ -624,8 +624,8 @@
306 >>> print browser.title
307 Questions for Foo Bar : Questions : Foo Bar
308 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
309- >>> for question in questions.fetch('td', 'questionTITLE'):
310- ... print question.first('a').renderContents()
311+ >>> for question in questions.findAll('td', 'questionTITLE'):
312+ ... print question.find('a').renderContents()
313 Slow system
314
315
316@@ -644,11 +644,11 @@
317
318 >>> def print_questions_with_target(contents):
319 ... questions = find_tag_by_id(contents, 'question-listing')
320- ... for question in questions.tbody.fetch('tr'):
321- ... question_title = question.first(
322- ... 'td', 'questionTITLE').first('a').renderContents()
323- ... question_target = question.first(
324- ... 'td', 'question-target').first('a').renderContents()
325+ ... for question in questions.tbody.findAll('tr'):
326+ ... question_title = question.find(
327+ ... 'td', 'questionTITLE').find('a').renderContents()
328+ ... question_target = question.find(
329+ ... 'td', 'question-target').find('a').renderContents()
330 ... print question_title, question_target
331 >>> print_questions_with_target(browser.contents)
332 Newly installed plug-in doesn't seem to be used Mozilla Firefox
333@@ -662,8 +662,8 @@
334 >>> browser.getControl('Search', index=0).click()
335
336 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
337- >>> for question in questions.fetch('td', 'questionTITLE'):
338- ... print question.first('a').renderContents()
339+ >>> for question in questions.findAll('td', 'questionTITLE'):
340+ ... print question.find('a').renderContents()
341 Problem showing the SVG demo on W3C site
342
343 The same standard reports than on regular QuestionTarget are available:
344@@ -724,7 +724,7 @@
345 >>> browser.getControl('Search', index=0).click()
346
347 >>> print find_main_content(
348- ... browser.contents).first('p').renderContents()
349+ ... browser.contents).find('p').renderContents()
350 There are no questions matching "firefox" with the requested statuses.
351
352 Clicking the 'Search' button without entering any search text will
353
354=== modified file 'lib/lp/answers/stories/question-edit.txt'
355--- lib/lp/answers/stories/question-edit.txt 2016-08-23 08:05:44 +0000
356+++ lib/lp/answers/stories/question-edit.txt 2017-10-23 00:36:01 +0000
357@@ -38,11 +38,11 @@
358 And viewing that page should show the updated information.
359
360 >>> soup = find_main_content(test_browser.contents)
361- >>> print soup.first('div', 'report').renderContents().strip()
362+ >>> print soup.find('div', 'report').renderContents().strip()
363 <p>Hi! I&#x27;m trying to learn about SVG but I can&#x27;t get it to
364 work at all in firefox. Maybe there is a plugin? Help! Thanks.
365 Mark</p>
366- >>> print soup.first('h1').renderContents()
367+ >>> print soup.find('h1').renderContents()
368 Problem showing the SVG demo on W3C web site
369
370 You can even modify the title and description of 'Answered' and
371
372=== modified file 'lib/lp/answers/stories/question-overview.txt'
373--- lib/lp/answers/stories/question-overview.txt 2014-11-27 22:13:36 +0000
374+++ lib/lp/answers/stories/question-overview.txt 2017-10-23 00:36:01 +0000
375@@ -32,7 +32,7 @@
376 >>> browser.getLink('Answers').click()
377
378 >>> soup = find_main_content(browser.contents)
379- >>> print soup.first('h1').renderContents()
380+ >>> print soup.find('h1').renderContents()
381 Questions for Mozilla Firefox
382
383 >>> browser.getLink('Firefox loses focus and gets stuck').url
384@@ -61,7 +61,7 @@
385 >>> print browser.title
386 Question #2 : ...
387
388- >>> print find_main_content(browser.contents).first('h1').renderContents()
389+ >>> print find_main_content(browser.contents).find('h1').renderContents()
390 Problem showing the SVG demo on W3C site
391
392
393@@ -197,7 +197,7 @@
394 >>> print browser.title
395 Questions : Foo Bar
396
397- >>> print find_main_content(browser.contents).first('h1').renderContents()
398+ >>> print find_main_content(browser.contents).find('h1').renderContents()
399 Questions for Foo Bar
400
401 >>> browser.getLink('Slow system').url
402
403=== modified file 'lib/lp/answers/stories/question-search-multiple-languages.txt'
404--- lib/lp/answers/stories/question-search-multiple-languages.txt 2016-01-26 15:47:37 +0000
405+++ lib/lp/answers/stories/question-search-multiple-languages.txt 2017-10-23 00:36:01 +0000
406@@ -14,8 +14,8 @@
407
408 >>> anon_browser.open('http://launchpad.dev/distros/ubuntu/+questions')
409 >>> soup = find_main_content(anon_browser.contents)
410- >>> for question in soup.fetch('td', 'questionTITLE'):
411- ... print question.first('a').renderContents()
412+ >>> for question in soup.findAll('td', 'questionTITLE'):
413+ ... print question.find('a').renderContents()
414 Continue playing after shutdown
415 Play DVDs in Totem
416 mailto: problem in webpage
417@@ -25,8 +25,8 @@
418 # Since we have more than 5 results, some of them are in the second batch.
419 >>> anon_browser.getLink('Next').click()
420 >>> soup = find_main_content(anon_browser.contents)
421- >>> for question in soup.fetch('td', 'questionTITLE'):
422- ... print question.first('a').renderContents()
423+ >>> for question in soup.findAll('td', 'questionTITLE'):
424+ ... print question.find('a').renderContents()
425 Installation failed
426
427 The questions match the languages inferred from by GeoIP
428@@ -46,7 +46,7 @@
429 >>> anon_browser.getControl('Search', index=0).click()
430 >>> table = find_tag_by_id(anon_browser.contents, 'question-listing')
431 >>> for question in table.findAll('td', 'questionTITLE'):
432- ... question.first('a').renderContents()
433+ ... question.find('a').renderContents()
434 'Problema al recompilar kernel con soporte smp (doble-n\xc3\xbacleo)'
435 'Continue playing after shutdown'
436 'Play DVDs in Totem'
437@@ -72,7 +72,7 @@
438 >>> anon_browser.getLink('Next').click()
439 >>> table = find_tag_by_id(anon_browser.contents, 'question-listing')
440 >>> for question in table.findAll('td', 'questionTITLE'):
441- ... question.first('a').renderContents()
442+ ... question.find('a').renderContents()
443 'Slow system'
444 'Installation failed'
445 '\xd8\xb9\xd9\x83\xd8\xb3 ...
446@@ -103,7 +103,7 @@
447 ...
448 LookupError: name 'field.language...
449
450- >>> content = find_main_content(anon_browser.contents).first('p')
451+ >>> content = find_main_content(anon_browser.contents).find('p')
452 >>> print content.renderContents()
453 There are no questions for Kubuntu with the requested statuses.
454
455@@ -132,8 +132,8 @@
456 True
457
458 >>> soup = find_main_content(anon_browser.contents)
459- >>> for question in soup.fetch('td', 'questionTITLE'):
460- ... question.first('a').renderContents()
461+ >>> for question in soup.findAll('td', 'questionTITLE'):
462+ ... question.find('a').renderContents()
463 'Problema al recompilar kernel con soporte smp (doble-n\xc3\xbacleo)'
464 'Continue playing after shutdown'
465 'Play DVDs in Totem'
466@@ -143,8 +143,8 @@
467 # Since we have more than 5 results, some of them are in the second batch.
468 >>> anon_browser.getLink('Next').click()
469 >>> soup = find_main_content(anon_browser.contents)
470- >>> for question in soup.fetch('td', 'questionTITLE'):
471- ... question.first('a').renderContents()
472+ >>> for question in soup.findAll('td', 'questionTITLE'):
473+ ... question.find('a').renderContents()
474 'Slow system'
475 'Installation failed'
476
477@@ -207,8 +207,8 @@
478 >>> browser.getControl('English (en)').selected = False
479 >>> browser.getControl('Search', index=0).click()
480 >>> content = find_main_content(browser.contents)
481- >>> for question in content.fetch('td', 'questionTITLE'):
482- ... question.first('a').renderContents()
483+ >>> for question in content.findAll('td', 'questionTITLE'):
484+ ... question.find('a').renderContents()
485 'Problema al recompilar kernel con soporte smp (doble-n\xc3\xbacleo)'
486
487 Some users, translators in particular, speak an English variant.
488@@ -247,8 +247,8 @@
489 >>> daf_browser.getControl('English (en)').selected = True
490 >>> daf_browser.getControl('Search', index=0).click()
491 >>> content = find_main_content(daf_browser.contents)
492- >>> for question in content.fetch('td', 'questionTITLE'):
493- ... question.first('a').renderContents()
494+ >>> for question in content.findAll('td', 'questionTITLE'):
495+ ... question.find('a').renderContents()
496 'Continue playing after shutdown'
497 'Play DVDs in Totem'
498 'mailto: problem in webpage'
499@@ -297,7 +297,7 @@
500
501 >>> content = find_main_content(user_browser.contents)
502 >>> for question in content.findAll('td', 'questionTITLE'):
503- ... question.first('a').renderContents()
504+ ... question.find('a').renderContents()
505 'Problemas de Impress\xc3\xa3o no Firefox'
506
507 The page in all other respects behaves like a question search page.
508
509=== modified file 'lib/lp/answers/stories/question-workflow.txt'
510--- lib/lp/answers/stories/question-workflow.txt 2016-01-26 15:47:37 +0000
511+++ lib/lp/answers/stories/question-workflow.txt 2017-10-23 00:36:01 +0000
512@@ -22,7 +22,7 @@
513
514 >>> def find_last_comment(contents):
515 ... soup = find_main_content(contents)
516- ... return soup.fetch('div', 'boardCommentBody')[-1]
517+ ... return soup.findAll('div', 'boardCommentBody')[-1]
518
519 >>> def print_last_comment(contents):
520 ... print extract_text(find_last_comment(contents))
521@@ -86,7 +86,7 @@
522
523 >>> support_browser.getControl('Add Information Request').click()
524 >>> soup = find_main_content(support_browser.contents)
525- >>> print soup.first('div', 'message').renderContents()
526+ >>> print soup.find('div', 'message').renderContents()
527 Please enter a message.
528
529
530@@ -179,7 +179,7 @@
531 >>> owner_browser.open(
532 ... 'http://launchpad.dev/firefox/+question/2')
533 >>> soup = find_main_content(owner_browser.contents)
534- >>> soup.fetch('div', 'boardComment')[-1].first('input', type='submit')
535+ >>> soup.findAll('div', 'boardComment')[-1].find('input', type='submit')
536 <input type="submit" name="field.actions.confirm"
537 value="This Solved My Problem" />
538
539@@ -214,11 +214,11 @@
540 The confirmed answer is also highlighted.
541
542 >>> soup = find_main_content(owner_browser.contents)
543- >>> bestAnswer = soup.fetch('div', 'boardComment')[-2]
544- >>> print bestAnswer.first('img')
545+ >>> bestAnswer = soup.findAll('div', 'boardComment')[-2]
546+ >>> print bestAnswer.find('img')
547 <img src="/@@/favourite-yes" ... title="Marked as best answer" />
548
549- >>> print soup.first(
550+ >>> print soup.find(
551 ... 'div', 'boardCommentBody highlighted').renderContents()
552 <p>New version of the firefox package are available with SVG support
553 enabled. You can use apt-get or adept to upgrade.</p>
554@@ -286,11 +286,11 @@
555 answerer back to None.
556
557 >>> soup = find_main_content(owner_browser.contents)
558- >>> bestAnswer = soup.fetch('div', 'boardComment')[-4]
559- >>> bestAnswer.first('strong') is None
560+ >>> bestAnswer = soup.findAll('div', 'boardComment')[-4]
561+ >>> bestAnswer.find('strong') is None
562 True
563
564- >>> bestAnswer.first('div', 'boardCommentBody')
565+ >>> bestAnswer.find('div', 'boardCommentBody')
566 <div class="boardCommentBody" itemprop="commentText"><p>New version
567 of the firefox package
568 are available with SVG support enabled. You can use apt-get or adept to
569@@ -325,7 +325,7 @@
570
571 >>> soup = find_tag_by_id(owner_browser.contents, 'portlet-details')
572 >>> soup = find_main_content(owner_browser.contents)
573- >>> bestAnswer = soup.first('img', {'title': 'Marked as best answer'})
574+ >>> bestAnswer = soup.find('img', {'title': 'Marked as best answer'})
575 >>> None == bestAnswer
576 True
577
578@@ -382,17 +382,17 @@
579 It lists all the actions performed through workflow on the question:
580
581 >>> soup = find_main_content(anon_browser.contents)
582- >>> action_listing = soup.first('table', 'listing')
583- >>> for header in action_listing.fetch('th'):
584+ >>> action_listing = soup.find('table', 'listing')
585+ >>> for header in action_listing.findAll('th'):
586 ... print header.renderContents()
587 When
588 Who
589 Action
590 New State
591
592- >>> for row in action_listing.first('tbody').fetch('tr'):
593- ... cells = row.fetch('td')
594- ... who = extract_text(cells[1].first('a'))
595+ >>> for row in action_listing.find('tbody').findAll('tr'):
596+ ... cells = row.findAll('td')
597+ ... who = extract_text(cells[1].find('a'))
598 ... action = cells[2].renderContents()
599 ... new_status = cells[3].renderContents()
600 ... print who.lstrip('&nbsp;'), action, new_status
601
602=== modified file 'lib/lp/answers/stories/questions-index.txt'
603--- lib/lp/answers/stories/questions-index.txt 2011-12-24 15:18:32 +0000
604+++ lib/lp/answers/stories/questions-index.txt 2017-10-23 00:36:01 +0000
605@@ -24,10 +24,10 @@
606
607 >>> latest_questions_asked = find_tag_by_id(
608 ... anon_browser.contents, 'latest-questions-asked')
609- >>> print latest_questions_asked.first('h2').renderContents()
610+ >>> print latest_questions_asked.find('h2').renderContents()
611 Latest questions asked
612- >>> for row in latest_questions_asked.fetch('li'):
613- ... row.first('a').renderContents()
614+ >>> for row in latest_questions_asked.findAll('li'):
615+ ... row.find('a').renderContents()
616 '...: Problemas de Impress\xc3\xa3o no Firefox'
617 '...: Problema al recompilar kernel con soporte smp (doble-n\xc3\xbacleo)'
618 '...: Continue playing after shutdown'
619@@ -38,10 +38,10 @@
620
621 >>> latest_questions_solved = find_tag_by_id(
622 ... anon_browser.contents, 'latest-questions-solved')
623- >>> print latest_questions_solved.first('h2').renderContents()
624+ >>> print latest_questions_solved.find('h2').renderContents()
625 Latest questions solved
626- >>> for row in latest_questions_solved.fetch('li'):
627- ... row.first('a').renderContents()
628+ >>> for row in latest_questions_solved.findAll('li'):
629+ ... row.find('a').renderContents()
630 '...: mailto: problem in webpage'
631
632 The application footer also contains a sample of stats for the application:
633
634=== modified file 'lib/lp/blueprints/stories/blueprints/xx-buglinks.txt'
635--- lib/lp/blueprints/stories/blueprints/xx-buglinks.txt 2011-03-17 02:34:25 +0000
636+++ lib/lp/blueprints/stories/blueprints/xx-buglinks.txt 2017-10-23 00:36:01 +0000
637@@ -41,7 +41,7 @@
638 link.
639
640 >>> soup = find_main_content(user_browser.contents)
641- >>> soup.first('div', 'informational message')
642+ >>> soup.find('div', 'informational message')
643 <div class="informational message">Added link to bug #4:
644 ...Reflow problems with complex page layouts...</div>
645
646@@ -64,5 +64,5 @@
647 A confirmation is displayed to the user.
648
649 >>> soup = find_main_content(user_browser.contents)
650- >>> soup.first('div', 'informational message')
651+ >>> soup.find('div', 'informational message')
652 <div class="informational message">Removed link to bug #4.</div>
653
654=== modified file 'lib/lp/blueprints/stories/sprints/xx-sprints.txt'
655--- lib/lp/blueprints/stories/sprints/xx-sprints.txt 2017-04-10 10:49:19 +0000
656+++ lib/lp/blueprints/stories/sprints/xx-sprints.txt 2017-10-23 00:36:01 +0000
657@@ -380,7 +380,7 @@
658 >>> def print_attendees(sprint_page):
659 ... """Print the attendees listed in the attendees portlet."""
660 ... attendees_portlet = find_portlet(sprint_page, 'Attendees')
661- ... for li in attendees_portlet.fetch('ul')[0].fetch('li'):
662+ ... for li in attendees_portlet.findAll('ul')[0].findAll('li'):
663 ... print li.a.string.encode('ascii', 'xmlcharrefreplace')
664
665 >>> print_attendees(browser.contents)
666
667=== modified file 'lib/lp/blueprints/stories/standalone/subscribing.txt'
668--- lib/lp/blueprints/stories/standalone/subscribing.txt 2012-09-19 04:09:06 +0000
669+++ lib/lp/blueprints/stories/standalone/subscribing.txt 2017-10-23 00:36:01 +0000
670@@ -162,7 +162,7 @@
671 >>> subscribers = find_tags_by_class(browser.contents, 'subscriber')
672 >>> for subscriber in subscribers:
673 ... a_tags = subscriber.findAll('a')
674- ... img = a_tags[0].first('img')
675+ ... img = a_tags[0].find('img')
676 ... print img['src'],
677 ... print a_tags[1].string
678 /@@/subscriber-essential Stuart Bishop
679@@ -187,7 +187,7 @@
680 >>> subscribers = find_tags_by_class(browser.contents, 'subscriber')
681 >>> for subscriber in subscribers:
682 ... a_tags = subscriber.findAll('a')
683- ... img = a_tags[0].first('img')
684+ ... img = a_tags[0].find('img')
685 ... print img['src'],
686 ... print a_tags[1].string
687 /@@/subscriber-inessential Stuart Bishop
688@@ -320,7 +320,7 @@
689 >>> subscribers = find_tags_by_class(browser.contents, 'subscriber')
690 >>> for subscriber in subscribers:
691 ... a_tags = subscriber.findAll('a')
692- ... img = a_tags[0].first('img')
693+ ... img = a_tags[0].find('img')
694 ... print img['src'],
695 ... print a_tags[1].string
696 /@@/subscriber-essential Andrew Bennetts
697
698=== modified file 'lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt'
699--- lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt 2013-09-27 04:13:23 +0000
700+++ lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt 2017-10-23 00:36:01 +0000
701@@ -20,7 +20,7 @@
702
703 >>> bugwatch_portlet = find_portlet(
704 ... user_browser.contents, 'Remote bug watches')
705- >>> for li_tag in bugwatch_portlet.fetch('li'):
706+ >>> for li_tag in bugwatch_portlet.findAll('li'):
707 ... print li_tag.findAll('a')[0].renderContents()
708 debbugs #42
709
710@@ -46,7 +46,7 @@
711
712 >>> bugwatch_portlet = find_portlet(
713 ... user_browser.contents, 'Remote bug watches')
714- >>> for li_tag in bugwatch_portlet.fetch('li'):
715+ >>> for li_tag in bugwatch_portlet.findAll('li'):
716 ... print li_tag.findAll('a')[0].string
717 debbugs #42
718
719
720=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-single-comment-view.txt'
721--- lib/lp/bugs/stories/bugs/xx-bug-single-comment-view.txt 2009-06-12 16:36:02 +0000
722+++ lib/lp/bugs/stories/bugs/xx-bug-single-comment-view.txt 2017-10-23 00:36:01 +0000
723@@ -10,7 +10,7 @@
724 ... soup = find_main_content(browser.contents)
725 ... comment_details = soup('div', 'boardCommentDetails')
726 ... for details in comment_details:
727- ... print details.first('strong').string
728+ ... print details.find('strong').string
729
730 >>> print_comment_titles(browser.contents)
731 Fantastic idea, I'd really like to see this
732
733=== modified file 'lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt'
734--- lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt 2016-01-26 15:47:37 +0000
735+++ lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt 2017-10-23 00:36:01 +0000
736@@ -205,9 +205,9 @@
737
738 >>> def names_and_branches(contents):
739 ... listing = find_tag_by_id(contents, 'bugs-table-listing')
740- ... for row in listing.fetch(None, {'class': 'buglisting-row'}):
741+ ... for row in listing.findAll(None, {'class': 'buglisting-row'}):
742 ... badge_cell = row.find(None, {'class': 'bug-related-icons'})
743- ... spans = badge_cell.fetch('span')
744+ ... spans = badge_cell.findAll('span')
745 ... for span in spans:
746 ... print " Badge:", span.get('alt')
747
748
749=== modified file 'lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt'
750--- lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt 2009-08-19 13:10:19 +0000
751+++ lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt 2017-10-23 00:36:01 +0000
752@@ -116,7 +116,7 @@
753 'http://bugs.launchpad.dev/debian/+source/mozilla-firefox/+bug/1'
754
755 >>> bugwatch_portlet = find_portlet(browser.contents, 'Remote bug watches')
756- >>> for li_tag in bugwatch_portlet.fetch('li'):
757+ >>> for li_tag in bugwatch_portlet.findAll('li'):
758 ... print li_tag.findAll('a')[0].string
759 mozilla.org #123543
760 mozilla.org #2000
761
762=== modified file 'lib/lp/bugs/stories/cve/cve-linking.txt'
763--- lib/lp/bugs/stories/cve/cve-linking.txt 2016-01-26 15:47:37 +0000
764+++ lib/lp/bugs/stories/cve/cve-linking.txt 2017-10-23 00:36:01 +0000
765@@ -62,7 +62,7 @@
766 A notification is displayed telling the user which bug they just linked:
767
768 >>> soup = find_main_content(user_browser.contents)
769- >>> soup.first('div', 'informational message')
770+ >>> soup.find('div', 'informational message')
771 <div class="informational message">Added link to bug #2:
772 ...Blackhole Trash folder...</div>
773
774
775=== modified file 'lib/lp/bugs/tests/bug.py'
776--- lib/lp/bugs/tests/bug.py 2017-10-23 00:36:01 +0000
777+++ lib/lp/bugs/tests/bug.py 2017-10-23 00:36:01 +0000
778@@ -80,7 +80,7 @@
779 :param highlighted_only: Only print the highlighted row
780 """
781 main_content = find_main_content(content)
782- affects_table = main_content.first('table', {'class': 'listing'})
783+ affects_table = main_content.find('table', {'class': 'listing'})
784 if highlighted_only:
785 tr_attrs = {'class': 'highlight'}
786 else:
787
788=== modified file 'lib/lp/code/stories/branches/xx-bazaar-home.txt'
789--- lib/lp/code/stories/branches/xx-bazaar-home.txt 2012-09-12 06:13:41 +0000
790+++ lib/lp/code/stories/branches/xx-bazaar-home.txt 2017-10-23 00:36:01 +0000
791@@ -34,7 +34,7 @@
792 Most active projects in the last month
793 see all projects&#8230;
794
795- >>> print preview.fetch('a')[-1]['href']
796+ >>> print preview.findAll('a')[-1]['href']
797 /projects
798
799
800@@ -72,7 +72,7 @@
801 registered branches first.
802
803 >>> registered = find_tag_by_id(browser.contents, 'recently-registered')
804- >>> print registered.fetch('a')[-1]['href']
805+ >>> print registered.findAll('a')[-1]['href']
806 /+recently-registered-branches
807
808 >>> browser.getLink(url='recently-registered-branches').click()
809@@ -84,7 +84,7 @@
810 registered is the ordering, the registered date is also shown.
811
812 >>> table = find_tag_by_id(browser.contents, 'branchtable')
813- >>> for row in table.thead.fetch('tr'):
814+ >>> for row in table.thead.findAll('tr'):
815 ... print extract_text(row)
816 Name
817 Status
818@@ -105,7 +105,7 @@
819
820 >>> browser.open('http://code.launchpad.dev/')
821 >>> changed = find_tag_by_id(browser.contents, 'recently-changed')
822- >>> print changed.fetch('a')[-1]['href']
823+ >>> print changed.findAll('a')[-1]['href']
824 /+recently-changed-branches
825
826 >>> browser.getLink(url='recently-changed-branches').click()
827@@ -113,7 +113,7 @@
828 Recently changed branches
829
830 >>> table = find_tag_by_id(browser.contents, 'branchtable')
831- >>> for row in table.thead.fetch('tr'):
832+ >>> for row in table.thead.findAll('tr'):
833 ... print extract_text(row)
834 Name
835 Status
836@@ -132,7 +132,7 @@
837
838 >>> browser.open('http://code.launchpad.dev/')
839 >>> imported = find_tag_by_id(browser.contents, 'recent-imports')
840- >>> print imported.fetch('a')[-1]['href']
841+ >>> print imported.findAll('a')[-1]['href']
842 /+recently-imported-branches
843
844 >>> browser.getLink(url='recently-imported-branches').click()
845@@ -144,7 +144,7 @@
846 imported branch listings.
847
848 >>> table = find_tag_by_id(browser.contents, 'branchtable')
849- >>> for row in table.thead.fetch('tr'):
850+ >>> for row in table.thead.findAll('tr'):
851 ... print extract_text(row)
852 Name
853 Status
854
855=== modified file 'lib/lp/code/stories/branches/xx-branch-listings-merge-proposal-badge.txt'
856--- lib/lp/code/stories/branches/xx-branch-listings-merge-proposal-badge.txt 2015-06-02 06:35:38 +0000
857+++ lib/lp/code/stories/branches/xx-branch-listings-merge-proposal-badge.txt 2017-10-23 00:36:01 +0000
858@@ -2,10 +2,10 @@
859
860 >>> def branchSummary(browser):
861 ... table = find_tag_by_id(browser.contents, 'branchtable')
862- ... for row in table.tbody.fetch('tr'):
863+ ... for row in table.tbody.findAll('tr'):
864 ... cells = row.findAll('td')
865 ... first_cell = cells[0]
866- ... anchors = first_cell.fetch('a')
867+ ... anchors = first_cell.findAll('a')
868 ... print anchors[0].get('href')
869 ... # Badges in the next cell
870 ... for img in cells[1].findAll('img'):
871
872=== modified file 'lib/lp/code/stories/branches/xx-branch-listings.txt'
873--- lib/lp/code/stories/branches/xx-branch-listings.txt 2016-01-26 15:47:37 +0000
874+++ lib/lp/code/stories/branches/xx-branch-listings.txt 2017-10-23 00:36:01 +0000
875@@ -28,7 +28,7 @@
876 ...1...&rarr;...6...of 10 results...
877
878 >>> table = find_tag_by_id(browser.contents, 'branchtable')
879- >>> for row in table.thead.fetch('tr'):
880+ >>> for row in table.thead.findAll('tr'):
881 ... print extract_text(row)
882 Name
883 Status
884@@ -39,7 +39,7 @@
885 fields. There are a couple of branches that have them, but most don't
886 and are really just branch metadata without the revisions behind them.
887
888- >>> for row in table.tbody.fetch('tr'):
889+ >>> for row in table.tbody.findAll('tr'):
890 ... print extract_text(row)
891 lp://dev/~name12/firefox/main Development ...
892 lp://dev/~name12/gnome-terminal/2.6 Mature ...
893@@ -55,7 +55,7 @@
894 ...7...&rarr;...10...of 10 results...
895
896 >>> table = find_tag_by_id(browser.contents, 'branchtable')
897- >>> for row in table.tbody.fetch('tr'):
898+ >>> for row in table.tbody.findAll('tr'):
899 ... print extract_text(row)
900 lp://dev/~name12/gnome-terminal/klingon Experimental ...
901 lp://dev/~name12/+junk/junk.contrib Development ...
902@@ -82,7 +82,7 @@
903
904 >>> browser.open('http://code.launchpad.dev/~name12')
905 >>> table = find_tag_by_id(browser.contents, 'branchtable')
906- >>> for row in table.tbody.fetch('tr'):
907+ >>> for row in table.tbody.findAll('tr'):
908 ... print extract_text(row)
909 lp://dev/~name12/firefox/main Development ...
910 lp://dev/~name12/gnome-terminal/2.6 Mature ...
911@@ -117,7 +117,7 @@
912 ...1...&rarr;...6...of 12 results...
913
914 >>> table = find_tag_by_id(browser.contents, 'branchtable')
915- >>> for row in table.tbody.fetch('tr'):
916+ >>> for row in table.tbody.findAll('tr'):
917 ... print extract_text(row)
918 lp://dev/~name12/firefox/main Development ...
919 lp://dev/~name12/gnome-terminal/2.4 Abandoned ...
920@@ -133,7 +133,7 @@
921 ...7...&rarr;...12...of 12 results...
922
923 >>> table = find_tag_by_id(browser.contents, 'branchtable')
924- >>> for row in table.tbody.fetch('tr'):
925+ >>> for row in table.tbody.findAll('tr'):
926 ... print extract_text(row)
927 lp://dev/~name12/gnome-terminal/pushed Development ...
928 lp://dev/~name12/gnome-terminal/scanned Development ...
929@@ -148,7 +148,7 @@
930 >>> browser.getControl(name='field.lifecycle').displayValue = ['Abandoned']
931 >>> browser.getControl('Filter').click()
932 >>> table = find_tag_by_id(browser.contents, 'branchtable')
933- >>> for row in table.tbody.fetch('tr'):
934+ >>> for row in table.tbody.findAll('tr'):
935 ... print extract_text(row)
936 lp://dev/~name12/gnome-terminal/2.4 Abandoned ...
937
938@@ -160,7 +160,7 @@
939 >>> browser.getControl(name='field.lifecycle').displayValue
940 ['Any active status']
941 >>> table = find_tag_by_id(browser.contents, 'branchtable')
942- >>> for row in table.tbody.fetch('tr'):
943+ >>> for row in table.tbody.findAll('tr'):
944 ... print extract_text(row)
945 lp://dev/~name12/firefox/main Development ...
946 lp://dev/~name12/gnome-terminal/2.6 Mature ...
947@@ -188,7 +188,7 @@
948 ... 'http://code.launchpad.dev/~name12/+branches?'
949 ... 'field.category=subscribed')
950 >>> table = find_tag_by_id(browser.contents, 'branchtable')
951- >>> for row in table.tbody.fetch('tr'):
952+ >>> for row in table.tbody.findAll('tr'):
953 ... print extract_text(row)
954 lp://dev/~name12/firefox/main ...
955 lp://dev/~launchpad/gnome-terminal/launchpad ...
956@@ -212,12 +212,12 @@
957
958 >>> def branchSummary(browser):
959 ... table = find_tag_by_id(browser.contents, 'branchtable')
960- ... for row in table.tbody.fetch('tr'):
961+ ... for row in table.tbody.findAll('tr'):
962 ... if row.getText().startswith('A development focus branch'):
963 ... continue
964 ... cells = row.findAll('td')
965 ... first_cell = cells[0]
966- ... anchors = first_cell.fetch('a')
967+ ... anchors = first_cell.findAll('a')
968 ... print anchors[0].get('href')
969 ... # Badges in the next cell
970 ... for img in cells[1].findAll('img'):
971@@ -334,7 +334,7 @@
972
973 >>> browser.open('http://code.launchpad.dev/gnome-terminal/+branches')
974 >>> table = find_tag_by_id(browser.contents, 'branchtable')
975- >>> for row in table.tbody.fetch('tr'):
976+ >>> for row in table.tbody.findAll('tr'):
977 ... print extract_text(row)
978 A development focus ...
979 lp://dev/~name12/gnome-terminal/2.6 Mature ...
980@@ -347,7 +347,7 @@
981 >>> browser.getControl(name='field.sort_by').value = ['by branch name']
982 >>> browser.getControl('Filter').click()
983 >>> table = find_tag_by_id(browser.contents, 'branchtable')
984- >>> for row in table.tbody.fetch('tr'):
985+ >>> for row in table.tbody.findAll('tr'):
986 ... print extract_text(row)
987 A development focus ...
988 lp://dev/~name12/gnome-terminal/2.6 Mature ...
989@@ -380,8 +380,8 @@
990 >>> browser.open('http://code.launchpad.dev/gnome-terminal')
991 >>> table = find_tag_by_id(browser.contents, 'branchtable')
992 >>> # The development focus is always first.
993- >>> row = table.tbody.fetch('tr')[0]
994- >>> cols = row.fetch('td')
995+ >>> row = table.tbody.findAll('tr')[0]
996+ >>> cols = row.findAll('td')
997 >>> print extract_text(cols[0])
998 lp://dev/gnome-terminal Series: trunk
999
1000@@ -408,7 +408,7 @@
1001
1002 >>> browser.open('http://code.launchpad.dev/gnome-terminal')
1003 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1004- >>> print extract_text(table.tbody.fetch('tr')[0])
1005+ >>> print extract_text(table.tbody.findAll('tr')[0])
1006 lp://dev/gnome-terminal Series: trunk, alpha, pre-1.0 ...
1007
1008
1009@@ -421,7 +421,7 @@
1010
1011 >>> browser.open('http://code.launchpad.dev/gnome-terminal')
1012 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1013- >>> for row in table.tbody.fetch('tr'):
1014+ >>> for row in table.tbody.findAll('tr'):
1015 ... print extract_text(row)
1016 lp://dev/gnome-terminal Series: trunk... Development ...
1017 lp://dev/~name12/gnome-terminal/2.6 Mature ...
1018@@ -446,7 +446,7 @@
1019 >>> browser.getControl(name='field.lifecycle').displayValue = ['Experimental']
1020 >>> browser.getControl('Filter').click()
1021 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1022- >>> for row in table.tbody.fetch('tr'):
1023+ >>> for row in table.tbody.findAll('tr'):
1024 ... print extract_text(row)
1025 lp://dev/~name12/gnome-terminal/klingon Experimental ...
1026
1027@@ -456,7 +456,7 @@
1028 >>> browser.getControl(name='field.lifecycle').displayValue = ['Development']
1029 >>> browser.getControl('Filter').click()
1030 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1031- >>> for row in table.tbody.fetch('tr'):
1032+ >>> for row in table.tbody.findAll('tr'):
1033 ... print extract_text(row)
1034 lp://dev/gnome-terminal Series: trunk... Development ...
1035
1036
1037=== modified file 'lib/lp/code/stories/branches/xx-branch-tag-cloud.txt'
1038--- lib/lp/code/stories/branches/xx-branch-tag-cloud.txt 2010-08-31 00:29:48 +0000
1039+++ lib/lp/code/stories/branches/xx-branch-tag-cloud.txt 2017-10-23 00:36:01 +0000
1040@@ -24,7 +24,7 @@
1041 the link is shown.
1042
1043 >>> tags = find_tag_by_id(anon_browser.contents, 'project-tags')
1044- >>> for anchor in tags.fetch('a'):
1045+ >>> for anchor in tags.findAll('a'):
1046 ... print anchor.renderContents(), anchor['class']
1047 linux cloud-size-largest cloud-medium
1048 wibble cloud-size-smallest cloud-dark
1049
1050=== modified file 'lib/lp/code/stories/branches/xx-person-branches.txt'
1051--- lib/lp/code/stories/branches/xx-person-branches.txt 2016-07-02 07:56:08 +0000
1052+++ lib/lp/code/stories/branches/xx-person-branches.txt 2017-10-23 00:36:01 +0000
1053@@ -46,7 +46,7 @@
1054
1055 >>> browser.open('http://code.launchpad.dev/~name12')
1056 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1057- >>> for row in table.tbody.fetch('tr'):
1058+ >>> for row in table.tbody.findAll('tr'):
1059 ... print extract_text(row)
1060 lp://dev/~name12/landscape/feature-x Development
1061 ...
1062@@ -64,7 +64,7 @@
1063 >>> print browser.title
1064 Code : Sample Person
1065 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1066- >>> for row in table.tbody.fetch('tr'):
1067+ >>> for row in table.tbody.findAll('tr'):
1068 ... print extract_text(row)
1069 lp://dev/~name12/landscape/feature-x Development
1070 ...
1071@@ -83,7 +83,7 @@
1072 >>> print browser.title
1073 Code : Sample Person
1074 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1075- >>> for row in table.tbody.fetch('tr'):
1076+ >>> for row in table.tbody.findAll('tr'):
1077 ... print extract_text(row)
1078 lp://dev/~launchpad/gnome-terminal/launchpad Development ...
1079 lp://dev/~name12/+junk/junk.dev Experimental ...
1080
1081=== modified file 'lib/lp/code/stories/branches/xx-private-branch-listings.txt'
1082--- lib/lp/code/stories/branches/xx-private-branch-listings.txt 2017-04-18 22:17:00 +0000
1083+++ lib/lp/code/stories/branches/xx-private-branch-listings.txt 2017-10-23 00:36:01 +0000
1084@@ -49,7 +49,7 @@
1085 >>> def print_recently_registered_branches(browser):
1086 ... browser.open('http://code.launchpad.dev')
1087 ... branches = find_tag_by_id(browser.contents, 'recently-registered')
1088- ... for list_item in branches.ul.fetch('li'):
1089+ ... for list_item in branches.ul.findAll('li'):
1090 ... print "%r" % list_item.renderContents()
1091
1092 When there is no logged in user, only public branches should be visible.
1093@@ -113,7 +113,7 @@
1094 ... print extract_text(find_tag_by_id(
1095 ... browser.contents, 'branch-summary'))
1096 ... else:
1097- ... for row in table.tbody.fetch('tr'):
1098+ ... for row in table.tbody.findAll('tr'):
1099 ... print extract_text(row)
1100
1101 >>> print_landscape_code_listing(anon_browser)
1102@@ -153,7 +153,7 @@
1103 ... browser.open(full_url)
1104 ... table = find_tag_by_id(browser.contents, 'branchtable')
1105 ... branches = []
1106- ... for row in table.tbody.fetch('tr'):
1107+ ... for row in table.tbody.findAll('tr'):
1108 ... branches.append(extract_text(row))
1109 ... landscape_branches = [branch for branch in branches
1110 ... if 'landscape' in branch]
1111
1112=== modified file 'lib/lp/code/stories/branches/xx-product-branches.txt'
1113--- lib/lp/code/stories/branches/xx-product-branches.txt 2016-01-26 15:47:37 +0000
1114+++ lib/lp/code/stories/branches/xx-product-branches.txt 2017-10-23 00:36:01 +0000
1115@@ -54,7 +54,7 @@
1116
1117 The 'Help' links go to the help wiki.
1118
1119- >>> for anchor in summary.fetch('a'):
1120+ >>> for anchor in summary.findAll('a'):
1121 ... print anchor['href']
1122 https://help.launchpad.net/Code
1123
1124@@ -123,7 +123,7 @@
1125
1126 >>> browser.open('http://code.launchpad.dev/firefox')
1127 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1128- >>> for row in table.tbody.fetch('tr')[0:2]:
1129+ >>> for row in table.tbody.findAll('tr')[0:2]:
1130 ... print extract_text(row)
1131 lp://dev/firefox
1132 Series: trunk, 1.0 Development ...
1133@@ -138,7 +138,7 @@
1134
1135 >>> browser.open('http://code.launchpad.dev/firefox')
1136 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1137- >>> for row in table.tbody.fetch('tr')[0:2]:
1138+ >>> for row in table.tbody.findAll('tr')[0:2]:
1139 ... print extract_text(row)
1140 lp://dev/firefox
1141 Series: trunk Development ...
1142@@ -159,7 +159,7 @@
1143
1144 >>> browser.open('http://code.launchpad.dev/firefox')
1145 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1146- >>> for row in table.tbody.fetch('tr')[0:2]:
1147+ >>> for row in table.tbody.findAll('tr')[0:2]:
1148 ... print extract_text(row)
1149 lp://dev/~mark/firefox/release-0.8 Development ...
1150
1151
1152=== modified file 'lib/lp/code/stories/branches/xx-product-overview.txt'
1153--- lib/lp/code/stories/branches/xx-product-overview.txt 2009-04-17 10:32:16 +0000
1154+++ lib/lp/code/stories/branches/xx-product-overview.txt 2017-10-23 00:36:01 +0000
1155@@ -10,7 +10,7 @@
1156 ... if branches is None:
1157 ... print "No 'Latest branches' portlet found at %s" % (url,)
1158 ... return
1159- ... for list_item in branches.fetch('li'):
1160+ ... for list_item in branches.findAll('li'):
1161 ... print extract_text(list_item)
1162
1163 >>> def make_branch_on_product(product, branch_name, person_name):
1164
1165=== modified file 'lib/lp/code/stories/branches/xx-project-branches.txt'
1166--- lib/lp/code/stories/branches/xx-project-branches.txt 2011-05-05 09:37:10 +0000
1167+++ lib/lp/code/stories/branches/xx-project-branches.txt 2017-10-23 00:36:01 +0000
1168@@ -24,7 +24,7 @@
1169
1170 >>> browser.open('http://code.launchpad.dev/mozilla')
1171 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1172- >>> for row in table.tbody.fetch('tr'):
1173+ >>> for row in table.tbody.findAll('tr'):
1174 ... print extract_text(row)
1175 lp://dev/~mark/firefox/release--0.9.1 Development firefox ...
1176 lp://dev/~mark/firefox/release-0.8 Development firefox ...
1177
1178=== modified file 'lib/lp/code/stories/branches/xx-source-package-branches-listing.txt'
1179--- lib/lp/code/stories/branches/xx-source-package-branches-listing.txt 2014-02-25 06:38:58 +0000
1180+++ lib/lp/code/stories/branches/xx-source-package-branches-listing.txt 2017-10-23 00:36:01 +0000
1181@@ -34,7 +34,7 @@
1182
1183 >>> def print_branches(browser):
1184 ... table = find_tag_by_id(browser.contents, 'branchtable')
1185- ... for row in table.tbody.fetch('tr'):
1186+ ... for row in table.tbody.findAll('tr'):
1187 ... print extract_text(row)
1188 >>> print_branches(browser)
1189 lp://dev/~owner1/distro/series/foo/branch1 ...
1190
1191=== modified file 'lib/lp/code/stories/branches/xx-subscribing-branches.txt'
1192--- lib/lp/code/stories/branches/xx-subscribing-branches.txt 2016-01-26 15:47:37 +0000
1193+++ lib/lp/code/stories/branches/xx-subscribing-branches.txt 2017-10-23 00:36:01 +0000
1194@@ -9,7 +9,7 @@
1195 ... if subscriptions == None:
1196 ... print subscriptions
1197 ... return
1198- ... for subscriber in subscriptions.fetch('div'):
1199+ ... for subscriber in subscriptions.findAll('div'):
1200 ... print extract_text(subscriber.renderContents())
1201
1202 Another to print the informational message.
1203
1204=== modified file 'lib/lp/code/stories/codeimport/xx-codeimport-results.txt'
1205--- lib/lp/code/stories/codeimport/xx-codeimport-results.txt 2011-12-20 23:28:22 +0000
1206+++ lib/lp/code/stories/codeimport/xx-codeimport-results.txt 2017-10-23 00:36:01 +0000
1207@@ -52,7 +52,7 @@
1208
1209 >>> # The ordering here is dependant on the order the status values
1210 >>> # are declared in the enumeration.
1211- >>> for img in import_results.fetch('img'):
1212+ >>> for img in import_results.findAll('img'):
1213 ... print img
1214 <img src="/@@/no" title="Unsupported feature" />
1215 <img src="/@@/no" title="Foreign branch invalid" />
1216@@ -64,7 +64,7 @@
1217
1218 >>> browser.open(branch_url_2)
1219 >>> import_results = find_tag_by_id(browser.contents, 'import-results')
1220- >>> for img in import_results.fetch('img'):
1221+ >>> for img in import_results.findAll('img'):
1222 ... print img
1223 <img src="/@@/no" title="Job killed" />
1224 <img src="/@@/no" title="Job reclaimed" />
1225
1226=== modified file 'lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt'
1227--- lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt 2016-10-14 16:16:18 +0000
1228+++ lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt 2017-10-23 00:36:01 +0000
1229@@ -7,12 +7,12 @@
1230
1231 >>> def print_recipe_listing_head(browser):
1232 ... table = find_tag_by_id(browser.contents, 'recipetable')
1233- ... for row in table.thead.fetch('tr'):
1234+ ... for row in table.thead.findAll('tr'):
1235 ... print extract_text(row)
1236
1237 >>> def print_recipe_listing_contents(browser):
1238 ... table = find_tag_by_id(browser.contents, 'recipetable')
1239- ... for row in table.tbody.fetch('tr'):
1240+ ... for row in table.tbody.findAll('tr'):
1241 ... print extract_text(row)
1242
1243
1244
1245=== modified file 'lib/lp/coop/answersbugs/stories/question-buglink.txt'
1246--- lib/lp/coop/answersbugs/stories/question-buglink.txt 2016-01-26 15:47:37 +0000
1247+++ lib/lp/coop/answersbugs/stories/question-buglink.txt 2017-10-23 00:36:01 +0000
1248@@ -33,7 +33,7 @@
1249 message is displayed:
1250
1251 >>> soup = find_main_content(user_browser.contents)
1252- >>> soup.first('div', 'message')
1253+ >>> soup.find('div', 'message')
1254 <div class="message">Not a valid bug number or nickname.</div>
1255
1256 The user is offered a link to search for bug in case they don't know the
1257@@ -82,7 +82,7 @@
1258 >>> user_browser.url
1259 '.../firefox/+question/2'
1260 >>> soup = find_main_content(user_browser.contents)
1261- >>> soup.first('div', 'informational message')
1262+ >>> soup.find('div', 'informational message')
1263 <div class="informational message">Removed link to bug #...</div>
1264 >>> print extract_text(
1265 ... find_tag_by_id(user_browser.contents, 'related-bugs'))
1266
1267=== modified file 'lib/lp/coop/answersbugs/stories/question-makebug.txt'
1268--- lib/lp/coop/answersbugs/stories/question-makebug.txt 2012-06-16 13:31:38 +0000
1269+++ lib/lp/coop/answersbugs/stories/question-makebug.txt 2017-10-23 00:36:01 +0000
1270@@ -53,7 +53,7 @@
1271 questions' portlet:
1272
1273 >>> portlet = find_portlet(browser.contents, 'Related questions')
1274- >>> for question in portlet.fetch('li', 'question-row'):
1275+ >>> for question in portlet.findAll('li', 'question-row'):
1276 ... print question.renderContents()
1277 <span class="sprite question">Mozilla Firefox</span>: ...<a href=".../firefox/+question/2">Problem...
1278
1279
1280=== modified file 'lib/lp/soyuz/stories/ppa/xx-private-ppa-presentation.txt'
1281--- lib/lp/soyuz/stories/ppa/xx-private-ppa-presentation.txt 2017-10-23 00:36:01 +0000
1282+++ lib/lp/soyuz/stories/ppa/xx-private-ppa-presentation.txt 2017-10-23 00:36:01 +0000
1283@@ -9,7 +9,7 @@
1284
1285 >>> browser.open("http://launchpad.dev/~cprov/+archive")
1286 >>> from lp.services.beautifulsoup import BeautifulSoup
1287- >>> body_el = BeautifulSoup(browser.contents).first('body')
1288+ >>> body_el = BeautifulSoup(browser.contents).find('body')
1289 >>> 'private' in body_el['class']
1290 False
1291
1292@@ -33,6 +33,6 @@
1293 >>> cprov_browser = setupBrowser(
1294 ... auth='Basic celso.providelo@canonical.com:test')
1295 >>> cprov_browser.open("http://launchpad.dev/~cprov/+archive/p3a")
1296- >>> body_el = BeautifulSoup(cprov_browser.contents).first('body')
1297+ >>> body_el = BeautifulSoup(cprov_browser.contents).find('body')
1298 >>> 'private' in body_el['class']
1299 True
1300
1301=== modified file 'lib/lp/translations/stories/standalone/xx-person-editlanguages.txt'
1302--- lib/lp/translations/stories/standalone/xx-person-editlanguages.txt 2016-01-26 15:47:37 +0000
1303+++ lib/lp/translations/stories/standalone/xx-person-editlanguages.txt 2017-10-23 00:36:01 +0000
1304@@ -105,7 +105,7 @@
1305
1306 >>> print find_spoken_languages(country_portlet)
1307 []
1308- >>> print country_portlet.first('a')['href']
1309+ >>> print country_portlet.find('a')['href']
1310 http://answers.launchpad.dev/launchpad
1311
1312 Back home in Brazil, Joao gets the equivalent for Brazil, where the
1313
1314=== modified file 'lib/lp/translations/stories/standalone/xx-pofile-export.txt'
1315--- lib/lp/translations/stories/standalone/xx-pofile-export.txt 2015-07-21 09:04:01 +0000
1316+++ lib/lp/translations/stories/standalone/xx-pofile-export.txt 2017-10-23 00:36:01 +0000
1317@@ -86,7 +86,7 @@
1318 ... browser.contents, 'Translation file details')
1319 >>> carlos = u'Carlos Perell\xf3 Mar\xedn'
1320 >>> creator = extract_text(
1321- ... translation_portlet.firstText('Creator:').findNext('a'))
1322+ ... translation_portlet.find(text='Creator:').findNext('a'))
1323 >>> carlos in creator
1324 True
1325
1326
1327=== modified file 'lib/lp/translations/stories/translationgroups/xx-translationgroups.txt'
1328--- lib/lp/translations/stories/translationgroups/xx-translationgroups.txt 2016-01-26 15:47:37 +0000
1329+++ lib/lp/translations/stories/translationgroups/xx-translationgroups.txt 2017-10-23 00:36:01 +0000
1330@@ -37,7 +37,7 @@
1331 >>> admin_browser.open(
1332 ... 'http://translations.launchpad.dev/+groups/+new')
1333 >>> print find_main_content(
1334- ... admin_browser.contents).first('h1').renderContents()
1335+ ... admin_browser.contents).find('h1').renderContents()
1336 Create a new translation group
1337
1338 Translation group names must meet certain conditions. For example, they