Merge ~cjwatson/launchpad:bs4-new-method-names into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: d917557beade1000f0650399e087e8c6b7a1edd3
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:bs4-new-method-names
Merge into: launchpad:master
Diff against target: 4245 lines (+447/-446)
153 files modified
lib/lp/answers/browser/tests/views.txt (+4/-4)
lib/lp/answers/stories/faq-browse-and-search.txt (+2/-2)
lib/lp/answers/stories/project-add-question.txt (+2/-2)
lib/lp/answers/stories/question-add-in-other-languages.txt (+1/-1)
lib/lp/answers/stories/question-add.txt (+2/-2)
lib/lp/answers/stories/question-browse-and-search.txt (+21/-21)
lib/lp/answers/stories/question-message.txt (+4/-4)
lib/lp/answers/stories/question-obfuscation.txt (+6/-6)
lib/lp/answers/stories/question-reject-and-change-status.txt (+4/-2)
lib/lp/answers/stories/question-search-multiple-languages.txt (+12/-12)
lib/lp/answers/stories/question-workflow.txt (+9/-9)
lib/lp/answers/stories/questions-index.txt (+2/-2)
lib/lp/answers/stories/this-is-a-faq.txt (+2/-2)
lib/lp/answers/tests/test_question_webservice.py (+1/-1)
lib/lp/app/browser/doc/base-layout.txt (+1/-1)
lib/lp/app/browser/tests/test_launchpadroot.py (+2/-2)
lib/lp/app/doc/hierarchical-menu.txt (+1/-1)
lib/lp/app/doc/launchpadform.txt (+2/-2)
lib/lp/app/doc/tales.txt (+1/-1)
lib/lp/app/stories/launchpad-root/xx-featuredprojects.txt (+3/-3)
lib/lp/app/widgets/doc/launchpad-radio-widget.txt (+1/-1)
lib/lp/app/widgets/tests/test_launchpadtarget.py (+1/-1)
lib/lp/blueprints/browser/tests/test_person_upcomingwork.py (+1/-1)
lib/lp/blueprints/stories/sprints/sprint-settopics.txt (+1/-1)
lib/lp/blueprints/stories/sprints/xx-sprint-meeting-export.txt (+2/-2)
lib/lp/blueprints/stories/sprints/xx-sprints.txt (+2/-2)
lib/lp/blueprints/stories/standalone/subscribing.txt (+3/-3)
lib/lp/bugs/browser/tests/test_bugtarget_filebug.py (+1/-1)
lib/lp/bugs/browser/tests/test_bugtask.py (+1/-1)
lib/lp/bugs/externalbugtracker/mantis.py (+2/-2)
lib/lp/bugs/externalbugtracker/sourceforge.py (+2/-2)
lib/lp/bugs/scripts/bzremotecomponentfinder.py (+1/-1)
lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt (+4/-4)
lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt (+4/-4)
lib/lp/bugs/stories/bug-tags/xx-official-bug-tags.txt (+1/-1)
lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt (+6/-6)
lib/lp/bugs/stories/bugattachments/xx-delete-bug-attachment.txt (+1/-1)
lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt (+6/-6)
lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt (+2/-2)
lib/lp/bugs/stories/bugs/xx-malone-homepage.txt (+1/-1)
lib/lp/bugs/stories/bugs/xx-remote-bug-comments.txt (+1/-1)
lib/lp/bugs/stories/bugs/xx-unique-ids-on-bug-page.txt (+1/-1)
lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt (+2/-2)
lib/lp/bugs/stories/bugtracker/bugtrackers-index.txt (+2/-2)
lib/lp/bugs/stories/bugtracker/xx-bugtracker.txt (+2/-2)
lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt (+2/-2)
lib/lp/bugs/stories/cve/cve-linking.txt (+1/-1)
lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt (+1/-1)
lib/lp/bugs/stories/guided-filebug/xx-displaying-similar-bugs.txt (+1/-1)
lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug.txt (+1/-1)
lib/lp/bugs/stories/guided-filebug/xx-filebug-attachments.txt (+1/-1)
lib/lp/bugs/stories/guided-filebug/xx-product-guided-filebug.txt (+2/-2)
lib/lp/bugs/stories/standalone/xx-show-distribution-cve-report.txt (+3/-3)
lib/lp/bugs/stories/standalone/xx-show-distrorelease-cve-report.txt (+1/-1)
lib/lp/bugs/tests/bug.py (+9/-9)
lib/lp/bugs/tests/test_bugs_webservice.py (+1/-1)
lib/lp/code/browser/codeimport.py (+1/-1)
lib/lp/code/browser/tests/test_branch.py (+2/-2)
lib/lp/code/browser/tests/test_gitlisting.py (+7/-7)
lib/lp/code/browser/tests/test_gitref.py (+5/-5)
lib/lp/code/browser/tests/test_gitrepository.py (+1/-1)
lib/lp/code/browser/tests/test_gitsubscription.py (+1/-1)
lib/lp/code/browser/tests/test_sourcepackagerecipe.py (+4/-4)
lib/lp/code/browser/widgets/tests/test_branchtargetwidget.py (+1/-1)
lib/lp/code/browser/widgets/tests/test_gitgrantee.py (+1/-1)
lib/lp/code/browser/widgets/tests/test_gitrefwidget.py (+1/-1)
lib/lp/code/browser/widgets/tests/test_gitrepositorytargetwidget.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 (+4/-4)
lib/lp/code/stories/branches/xx-branch-listings.txt (+21/-21)
lib/lp/code/stories/branches/xx-branch-tag-cloud.txt (+1/-1)
lib/lp/code/stories/branches/xx-branchmergeproposals.txt (+1/-1)
lib/lp/code/stories/branches/xx-code-review-comments.txt (+2/-2)
lib/lp/code/stories/branches/xx-nearby-branches.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 (+6/-6)
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-propose-for-merging.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-makebug.txt (+1/-1)
lib/lp/registry/browser/tests/coc-views.txt (+1/-1)
lib/lp/registry/browser/tests/packaging-views.txt (+1/-1)
lib/lp/registry/browser/tests/sourcepackage-views.txt (+1/-1)
lib/lp/registry/browser/tests/test_distroseries.py (+8/-8)
lib/lp/registry/browser/tests/test_distroseriesdifference_views.py (+11/-11)
lib/lp/registry/browser/tests/test_product.py (+2/-2)
lib/lp/registry/doc/product-widgets.txt (+1/-1)
lib/lp/registry/stories/announcements/xx-announcements.txt (+1/-1)
lib/lp/registry/stories/distributionmirror/xx-distribution-mirrors.txt (+2/-2)
lib/lp/registry/stories/milestone/object-milestones.txt (+5/-5)
lib/lp/registry/stories/person/xx-admin-person-review.txt (+1/-1)
lib/lp/registry/stories/person/xx-person-edit-jabber-ids.txt (+1/-1)
lib/lp/registry/stories/person/xx-person-home.txt (+2/-2)
lib/lp/registry/stories/person/xx-person-karma.txt (+3/-3)
lib/lp/registry/stories/person/xx-person-projects.txt (+1/-1)
lib/lp/registry/stories/person/xx-person-subscriptions.txt (+5/-5)
lib/lp/registry/stories/pillar/xx-pillar-sprints.txt (+1/-1)
lib/lp/registry/stories/product/xx-launchpad-project-search.txt (+1/-1)
lib/lp/registry/stories/product/xx-product-code-trunk.txt (+3/-3)
lib/lp/registry/stories/product/xx-product-files.txt (+9/-9)
lib/lp/registry/stories/product/xx-product-index.txt (+2/-2)
lib/lp/registry/stories/productseries/xx-productseries-index.txt (+2/-2)
lib/lp/registry/stories/team/xx-team-claim.txt (+1/-1)
lib/lp/registry/stories/teammembership/xx-teammembership.txt (+3/-3)
lib/lp/registry/tests/test_product.py (+2/-2)
lib/lp/services/feeds/feed.py (+1/-1)
lib/lp/services/feeds/stories/xx-links.txt (+22/-22)
lib/lp/services/oauth/doc/oauth-pages.txt (+1/-1)
lib/lp/services/oauth/stories/authorize-token.txt (+2/-2)
lib/lp/services/oauth/stories/managing-tokens.txt (+7/-7)
lib/lp/services/webapp/tests/test_login.py (+1/-1)
lib/lp/snappy/browser/widgets/tests/test_snaparchivewidget.py (+1/-1)
lib/lp/snappy/browser/widgets/tests/test_snapbuildchannelswidget.py (+1/-1)
lib/lp/snappy/browser/widgets/tests/test_storechannelswidget.py (+1/-1)
lib/lp/soyuz/browser/tests/test_archive_packages.py (+2/-2)
lib/lp/soyuz/stories/ppa/xx-ppa-packages.txt (+3/-3)
lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt (+1/-1)
lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt (+1/-1)
lib/lp/soyuz/stories/soyuz/xx-distroarchseries-binpackages.txt (+1/-1)
lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt (+1/-1)
lib/lp/soyuz/stories/soyuz/xx-packagepublishinghistory.txt (+1/-1)
lib/lp/soyuz/stories/soyuz/xx-person-packages.txt (+1/-1)
lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt (+1/-1)
lib/lp/testing/matchers.py (+3/-3)
lib/lp/testing/pages.py (+13/-13)
lib/lp/translations/stories/distribution/xx-distribution-translations.txt (+2/-2)
lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt (+1/-1)
lib/lp/translations/stories/importqueue/xx-translation-import-queue-filtering.txt (+2/-2)
lib/lp/translations/stories/importqueue/xx-translation-import-queue-targets.txt (+10/-11)
lib/lp/translations/stories/productseries/xx-productseries-translations.txt (+5/-5)
lib/lp/translations/stories/standalone/xx-licensing.txt (+2/-2)
lib/lp/translations/stories/standalone/xx-person-activity.txt (+1/-1)
lib/lp/translations/stories/standalone/xx-pofile-details.txt (+2/-2)
lib/lp/translations/stories/standalone/xx-pofile-export.txt (+1/-1)
lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt (+1/-1)
lib/lp/translations/stories/standalone/xx-pofile-translate-newlines-check.txt (+1/-1)
lib/lp/translations/stories/standalone/xx-pofile-translate.txt (+3/-3)
lib/lp/translations/stories/standalone/xx-potemplate-index.txt (+4/-4)
lib/lp/translations/stories/standalone/xx-product-translations.txt (+1/-1)
lib/lp/translations/stories/standalone/xx-rosetta-distributionsourcepackage-list.txt (+2/-2)
lib/lp/translations/stories/standalone/xx-rosetta-homepage.txt (+4/-4)
lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt (+4/-4)
lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt (+3/-3)
lib/lp/translations/stories/standalone/xx-translations-to-review.txt (+2/-2)
lib/lp/translations/stories/translationgroups/xx-link-to-documentation.txt (+5/-5)
lib/lp/translations/stories/translationgroups/xx-translationgroups.txt (+13/-13)
lib/lp/translations/stories/translations/xx-translations.txt (+2/-2)
utilities/roundup-sniffer.py (+1/-1)
Reviewer Review Type Date Requested Status
Ioana Lasc (community) Approve
Review via email: mp+400877@code.launchpad.net

Commit message

Use BS4-style method names consistently

To post a comment you must log in.
Revision history for this message
Ioana Lasc (ilasc) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/answers/browser/tests/views.txt b/lib/lp/answers/browser/tests/views.txt
2index 7fe71fc..d481a9c 100644
3--- a/lib/lp/answers/browser/tests/views.txt
4+++ b/lib/lp/answers/browser/tests/views.txt
5@@ -939,7 +939,7 @@ Summary, Created, Submitter, Assignee, and Status.
6 False
7
8 >>> table = find_tag_by_id(view.render(), 'question-listing')
9- >>> for row in table.findAll('tr'):
10+ >>> for row in table.find_all('tr'):
11 ... print(extract_text(row))
12 Summary Created Submitter Assignee Status
13 6 Newly installed... 2005-10-14 Sample Person — Answered ...
14@@ -956,7 +956,7 @@ package is displayed if it exists.
15 False
16
17 >>> table = find_tag_by_id(view.render(), 'question-listing')
18- >>> for row in table.findAll('tr'):
19+ >>> for row in table.find_all('tr'):
20 ... print(extract_text(row))
21 Summary Created Submitter Source Package Assignee Status ...
22 8 ... 2006-07-20 Sample Person mozilla-firefox — Answered
23@@ -976,7 +976,7 @@ ProjectGroups display the "In" column to show the product name.
24 True
25
26 >>> table = find_tag_by_id(view.render(), 'question-listing')
27- >>> for row in table.findAll('tr'):
28+ >>> for row in table.find_all('tr'):
29 ... print(extract_text(row))
30 Summary Created Submitter In Assignee Status
31 6 ... 2005-10-14 Sample Person Mozilla Firefox — Answered...
32@@ -996,7 +996,7 @@ to the question, or an m-dash if there is no assignee.
33 False
34
35 >>> table = find_tag_by_id(view.render(), 'question-listing')
36- >>> for row in table.findAll('tr'):
37+ >>> for row in table.find_all('tr'):
38 ... print(extract_text(row))
39 Summary Created Submitter Assignee Status
40 6 ... 2005-10-14 Sample Person Bob Answered
41diff --git a/lib/lp/answers/stories/faq-browse-and-search.txt b/lib/lp/answers/stories/faq-browse-and-search.txt
42index 1308adf..51ba8eb 100644
43--- a/lib/lp/answers/stories/faq-browse-and-search.txt
44+++ b/lib/lp/answers/stories/faq-browse-and-search.txt
45@@ -72,7 +72,7 @@ a pop-up:
46 >>> browser.getLink('First').click()
47 >>> faq_link = find_main_content(browser.contents).find(
48 ... 'a', text=re.compile('How can I play MP3/Divx/DVDs'))
49- >>> print(faq_link.findParent('li')['title'])
50+ >>> print(faq_link.find_parent('li')['title'])
51 Playing many common formats such as DVIX, MP3, DVD, or Flash ...
52
53 She clicks on FAQ's title to display the complete FAQ content:
54@@ -136,7 +136,7 @@ Following the link will show the questions results:
55 Questions : Ubuntu
56
57 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
58- >>> for question in questions.findAll('td', 'questionTITLE'):
59+ >>> for question in questions.find_all('td', 'questionTITLE'):
60 ... print(question.find('a').decode_contents())
61 Installation of Java Runtime Environment for Mozilla
62
63diff --git a/lib/lp/answers/stories/project-add-question.txt b/lib/lp/answers/stories/project-add-question.txt
64index dba5767..eb3703c 100644
65--- a/lib/lp/answers/stories/project-add-question.txt
66+++ b/lib/lp/answers/stories/project-add-question.txt
67@@ -78,7 +78,7 @@ that they submitted:
68
69 >>> similar_questions = find_tag_by_id(
70 ... user_browser.contents, 'similar-questions')
71- >>> for row in similar_questions.findAll('li'):
72+ >>> for row in similar_questions.find_all('li'):
73 ... print(row.a.decode_contents())
74 2: Problem showing the SVG demo on W3C site
75
76@@ -177,7 +177,7 @@ speaks Japanese, so we will use him.
77 ... 'Mozilla Thunderbird').selected = True
78 >>> daf_browser.getControl('Continue').click()
79 >>> content = find_main_content(daf_browser.contents)
80- >>> for message in content.findAll('div', 'informational message'):
81+ >>> for message in content.find_all('div', 'informational message'):
82 ... print(message.decode_contents())
83 You have been added as an answer contact for Mozilla Thunderbird.
84
85diff --git a/lib/lp/answers/stories/question-add-in-other-languages.txt b/lib/lp/answers/stories/question-add-in-other-languages.txt
86index a153f2b..9ec7b8d 100644
87--- a/lib/lp/answers/stories/question-add-in-other-languages.txt
88+++ b/lib/lp/answers/stories/question-add-in-other-languages.txt
89@@ -49,7 +49,7 @@ understood by any member of the support community.
90 able to test this case again. Note that in production this exact use case
91 already finds nothing.
92
93- #>>> for row in similar_questions.findAll('tr', 'noted'):
94+ #>>> for row in similar_questions.find_all('tr', 'noted'):
95 #... row.find('a').decode_contents()
96 #'Installation of Java Runtime Environment for Mozilla'
97 #'Problema al recompilar kernel con soporte smp (doble-n\xc3\xbacleo)'
98diff --git a/lib/lp/answers/stories/question-add.txt b/lib/lp/answers/stories/question-add.txt
99index 73e5ac1..e7debb4 100644
100--- a/lib/lp/answers/stories/question-add.txt
101+++ b/lib/lp/answers/stories/question-add.txt
102@@ -102,7 +102,7 @@ mouse is left over the question's title.
103 >>> import re
104 >>> question_link = contents.find(
105 ... 'a', text=re.compile('Installation of Java'))
106- >>> print(question_link.findParent('li')['title'])
107+ >>> print(question_link.find_parent('li')['title'])
108 <BLANKLINE>
109 When opening http://www.gotomypc.com/ with Mozilla, a java run time
110 ennvironment plugin is requested.
111@@ -117,7 +117,7 @@ hovers on the FAQ's title:
112
113 >>> faq_link = contents.find(
114 ... 'a', text=re.compile('How can I play MP3/Divx'))
115- >>> print(faq_link.findParent('li')['title'])
116+ >>> print(faq_link.find_parent('li')['title'])
117 Playing many common formats such as DVIX, MP3, DVD, or Flash
118 animations require the installation of plugins.
119 <BLANKLINE>
120diff --git a/lib/lp/answers/stories/question-browse-and-search.txt b/lib/lp/answers/stories/question-browse-and-search.txt
121index e537ec6..6c5bc69 100644
122--- a/lib/lp/answers/stories/question-browse-and-search.txt
123+++ b/lib/lp/answers/stories/question-browse-and-search.txt
124@@ -58,7 +58,7 @@ Answers page and goes there to check.
125 He sees a listing of the current questions posted on Ubuntu:
126
127 >>> soup = find_main_content(browser.contents)
128- >>> for question in soup.findAll('td', 'questionTITLE'):
129+ >>> for question in soup.find_all('td', 'questionTITLE'):
130 ... print(question.find('a').decode_contents())
131 Continue playing after shutdown
132 Play DVDs in Totem
133@@ -74,7 +74,7 @@ results. There, he finds only one other question:
134 >>> print(browser.title)
135 Questions : Ubuntu
136 >>> soup = find_main_content(browser.contents)
137- >>> for question in soup.findAll('td', 'questionTITLE'):
138+ >>> for question in soup.find_all('td', 'questionTITLE'):
139 ... print(question.find('a').decode_contents())
140 Installation failed
141
142@@ -125,11 +125,11 @@ description appears in a small pop-up:
143 >>> import re
144 >>> soup = find_main_content(browser.contents)
145 >>> question_link = soup.find('a', text=re.compile('Play DVDs'))
146- >>> print(question_link.findParent('tr')['title'])
147+ >>> print(question_link.find_parent('tr')['title'])
148 How do you play DVDs in Totem..........?
149
150 >>> question_link = soup.find('a', text=re.compile('Slow system'))
151- >>> print(question_link.findParent('tr')['title'])
152+ >>> print(question_link.find_parent('tr')['title'])
153 I get really poor hard drive performance.
154
155 He clicks on the question title to obtain the question page where the
156@@ -229,7 +229,7 @@ selected. He adds 'Invalid' to the selection, and run his search again.
157 This time, the search returns one item.
158
159 >>> soup = find_main_content(browser.contents)
160- >>> for question in soup.findAll('td', 'questionTITLE'):
161+ >>> for question in soup.find_all('td', 'questionTITLE'):
162 ... print(question.find('a').decode_contents())
163 Firefox is slow and consumes too much RAM
164
165@@ -304,7 +304,7 @@ recent questions on Mozilla Firefox.
166 >>> print(browser.title)
167 Questions : Mozilla Firefox
168 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
169- >>> for question in questions.findAll('td', 'questionTITLE'):
170+ >>> for question in questions.find_all('td', 'questionTITLE'):
171 ... print(question.find('a').decode_contents())
172 Firefox loses focus and gets stuck
173 Problem showing the SVG demo on W3C site
174@@ -324,7 +324,7 @@ problems:
175 >>> browser.getControl(name='field.search_text').value = 'plugin'
176 >>> browser.getControl('Search', index=0).click()
177 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
178- >>> for question in questions.findAll('td', 'questionTITLE'):
179+ >>> for question in questions.find_all('td', 'questionTITLE'):
180 ... print(question.find('a').decode_contents())
181 Problem showing the SVG demo on W3C site
182
183@@ -344,7 +344,7 @@ questions.)
184 >>> [strip_label(status) for status in statuses]
185 ['Answered', 'Solved']
186 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
187- >>> for question in questions.findAll('td', 'questionTITLE'):
188+ >>> for question in questions.find_all('td', 'questionTITLE'):
189 ... print(question.find('a').decode_contents())
190 Play DVDs in Totem
191 mailto: problem in webpage
192@@ -390,7 +390,7 @@ They need to login to access that page:
193 'Questions you asked about mozilla-firefox in Ubuntu : Questions : mozilla-firefox package : Ubuntu'
194 >>> questions = find_tag_by_id(
195 ... sample_person_browser.contents, 'question-listing')
196- >>> for question in questions.findAll('td', 'questionTITLE'):
197+ >>> for question in questions.find_all('td', 'questionTITLE'):
198 ... print(question.find('a').decode_contents())
199 mailto: problem in webpage
200 Installation of Java Runtime Environment for Mozilla
201@@ -412,7 +412,7 @@ The exact question they were searching for is displayed!
202
203 >>> questions = find_tag_by_id(
204 ... sample_person_browser.contents, 'question-listing')
205- >>> for question in questions.findAll('td', 'questionTITLE'):
206+ >>> for question in questions.find_all('td', 'questionTITLE'):
207 ... print(question.find('a').decode_contents())
208 mailto: problem in webpage
209
210@@ -459,7 +459,7 @@ They need to login to access that page:
211 Questions needing your attention for Ubuntu : Questions : Ubuntu
212 >>> questions = find_tag_by_id(
213 ... sample_person_browser.contents, 'question-listing')
214- >>> for question in questions.findAll('td', 'questionTITLE'):
215+ >>> for question in questions.find_all('td', 'questionTITLE'):
216 ... print(question.find('a').decode_contents())
217 Play DVDs in Totem
218 Installation of Java Runtime Environment for Mozilla
219@@ -504,7 +504,7 @@ commented on.
220 Questions : Foo Bar
221
222 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
223- >>> for question in questions.findAll('td', 'questionTITLE'):
224+ >>> for question in questions.find_all('td', 'questionTITLE'):
225 ... print(question.find('a').decode_contents())
226 Continue playing after shutdown
227 Play DVDs in Totem
228@@ -520,7 +520,7 @@ That listing is batched when there are many questions:
229 The listing contains a 'In' column that shows the context where the
230 questions was made.
231
232- >>> for question in questions.findAll('td', 'question-target'):
233+ >>> for question in questions.find_all('td', 'question-target'):
234 ... print(question.find('a').decode_contents())
235 Ubuntu
236 Ubuntu
237@@ -544,7 +544,7 @@ questions to a particular status:
238 ... 'Solved', 'Invalid']
239 >>> browser.getControl('Search', index=0).click()
240 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
241- >>> for question in questions.findAll('td', 'questionTITLE'):
242+ >>> for question in questions.find_all('td', 'questionTITLE'):
243 ... print(question.find('a').decode_contents())
244 Firefox is slow and consumes too much RAM
245 mailto: problem in webpage
246@@ -574,7 +574,7 @@ answerer.
247 >>> print(browser.title)
248 Questions for Foo Bar : Questions : Foo Bar
249 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
250- >>> for question in questions.findAll('td', 'questionTITLE'):
251+ >>> for question in questions.find_all('td', 'questionTITLE'):
252 ... print(question.find('a').decode_contents())
253 mailto: problem in webpage
254
255@@ -588,7 +588,7 @@ questions commented on by the person.
256 >>> print(browser.title)
257 Questions for Foo Bar : Questions : Foo Bar
258 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
259- >>> for question in questions.findAll('td', 'questionTITLE'):
260+ >>> for question in questions.find_all('td', 'questionTITLE'):
261 ... print(question.find('a').decode_contents())
262 Continue playing after shutdown
263 Play DVDs in Totem
264@@ -606,7 +606,7 @@ asked by the person.
265 >>> print(browser.title)
266 Questions for Foo Bar : Questions : Foo Bar
267 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
268- >>> for question in questions.findAll('td', 'questionTITLE'):
269+ >>> for question in questions.find_all('td', 'questionTITLE'):
270 ... print(question.find('a').decode_contents())
271 Slow system
272 Firefox loses focus and gets stuck
273@@ -621,7 +621,7 @@ the attention of that person.
274 >>> print(browser.title)
275 Questions for Foo Bar : Questions : Foo Bar
276 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
277- >>> for question in questions.findAll('td', 'questionTITLE'):
278+ >>> for question in questions.find_all('td', 'questionTITLE'):
279 ... print(question.find('a').decode_contents())
280 Continue playing after shutdown
281 Slow system
282@@ -636,7 +636,7 @@ visiting the 'Subscribed' link in the 'Answers' facet.
283 >>> print(browser.title)
284 Questions for Foo Bar : Questions : Foo Bar
285 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
286- >>> for question in questions.findAll('td', 'questionTITLE'):
287+ >>> for question in questions.find_all('td', 'questionTITLE'):
288 ... print(question.find('a').decode_contents())
289 Slow system
290
291@@ -656,7 +656,7 @@ there is an 'In' column displaying where the questions were filed.
292
293 >>> def print_questions_with_target(contents):
294 ... questions = find_tag_by_id(contents, 'question-listing')
295- ... for question in questions.tbody.findAll('tr'):
296+ ... for question in questions.tbody.find_all('tr'):
297 ... question_title = question.find(
298 ... 'td', 'questionTITLE').find('a').decode_contents()
299 ... question_target = question.find(
300@@ -674,7 +674,7 @@ That listing is searchable:
301 >>> browser.getControl('Search', index=0).click()
302
303 >>> questions = find_tag_by_id(browser.contents, 'question-listing')
304- >>> for question in questions.findAll('td', 'questionTITLE'):
305+ >>> for question in questions.find_all('td', 'questionTITLE'):
306 ... print(question.find('a').decode_contents())
307 Problem showing the SVG demo on W3C site
308
309diff --git a/lib/lp/answers/stories/question-message.txt b/lib/lp/answers/stories/question-message.txt
310index 84444ce..0afd96b 100644
311--- a/lib/lp/answers/stories/question-message.txt
312+++ b/lib/lp/answers/stories/question-message.txt
313@@ -40,7 +40,7 @@ authenticated already, so they will see 'human@somewhere.org'.
314 Question #11 : ...
315 >>> text = find_tags_by_class(
316 ... user_browser.contents, 'boardCommentBody')[-1]
317- >>> print(extract_text(text.findAll('p')[-1]))
318+ >>> print(extract_text(text.find_all('p')[-1]))
319 --
320 ______________________
321 human@somewhere.org
322@@ -56,7 +56,7 @@ see the obfuscated email address (<email address hidden>).
323
324 >>> text = find_tags_by_class(
325 ... anon_browser.contents, 'boardCommentBody')[-1]
326- >>> print(extract_text(text.findAll('p')[-1]))
327+ >>> print(extract_text(text.find_all('p')[-1]))
328 --
329 ______________________
330 &lt;email address hidden&gt;
331@@ -74,7 +74,7 @@ Signatures are identified by paragraphs with a starting line like '--'.
332 The entire content of the paragraph is wrapped by a tag of 'foldable'
333 class.
334
335- >>> print(text.findAll('p')[-1])
336+ >>> print(text.find_all('p')[-1])
337 <p><span class="foldable">--...
338 &lt;email address hidden&gt;<br/>
339 Witty signatures rock!
340@@ -87,7 +87,7 @@ preceded by a citation line. Only the quoted lines are wrapped with a
341 tag of 'foldable' class, citation lines are always displayed. Again
342 we can continue with the anonymous user to see the markup.
343
344- >>> print(text.findAll('p')[-2])
345+ >>> print(text.find_all('p')[-2])
346 <p>Somebody said sometime ago:<br/>
347 <span class="foldable-quoted">
348 &gt; 1. Remove the letters c, j, q, x, w<br/>
349diff --git a/lib/lp/answers/stories/question-obfuscation.txt b/lib/lp/answers/stories/question-obfuscation.txt
350index 51f8028..87133b1 100644
351--- a/lib/lp/answers/stories/question-obfuscation.txt
352+++ b/lib/lp/answers/stories/question-obfuscation.txt
353@@ -15,7 +15,7 @@ front page.
354 >>> user_browser.open('http://answers.launchpad.test/')
355 >>> question_portlet = find_tag_by_id(
356 ... user_browser.contents, 'latest-questions-solved')
357- >>> for li in question_portlet.findAll('li'):
358+ >>> for li in question_portlet.find_all('li'):
359 ... print(li['title'])
360 I am not able to ... if i click on a mailto:user@domain.com link ...
361
362@@ -30,7 +30,7 @@ in the question's description.
363
364 >>> question_listing = find_tag_by_id(
365 ... user_browser.contents, 'question-listing')
366- >>> for li in question_portlet.findAll('li'):
367+ >>> for li in question_portlet.find_all('li'):
368 ... print(li['title'])
369 I am not able to ... if i click on a mailto:user@domain.com link ...
370
371@@ -81,7 +81,7 @@ description. They can then see the email address in the tooltip in the
372 >>> user_browser.open('http://answers.launchpad.test/')
373 >>> question_portlet = find_tag_by_id(
374 ... user_browser.contents, 'latest-questions-asked')
375- >>> for li in question_portlet.findAll('li'):
376+ >>> for li in question_portlet.find_all('li'):
377 ... print(li['title'])
378 The clicking mailto:user@domain.com crashes the browser.
379 ...
380@@ -98,14 +98,14 @@ page.
381
382 >>> question_portlet = find_tag_by_id(
383 ... anon_browser.contents, 'latest-questions-solved')
384- >>> for li in question_portlet.findAll('li'):
385+ >>> for li in question_portlet.find_all('li'):
386 ... print(li['title'])
387 I am not able to ... if i click on a
388 mailto:<email address hidden> ...
389
390 >>> question_portlet = find_tag_by_id(
391 ... anon_browser.contents, 'latest-questions-asked')
392- >>> for li in question_portlet.findAll('li'):
393+ >>> for li in question_portlet.find_all('li'):
394 ... print(li['title'])
395 The clicking mailto:<email address hidden> crashes the browser.
396 ...
397@@ -123,7 +123,7 @@ They cannot see the address reading the question either.
398
399 >>> question_listing = find_tag_by_id(
400 ... anon_browser.contents, 'question-listing')
401- >>> for tr in question_listing.tbody.findAll('tr'):
402+ >>> for tr in question_listing.tbody.find_all('tr'):
403 ... print(tr['title'])
404 I am not able to ... if i click on a mailto:<email address hidden>
405 link ...
406diff --git a/lib/lp/answers/stories/question-reject-and-change-status.txt b/lib/lp/answers/stories/question-reject-and-change-status.txt
407index 44467a4..ece123c 100644
408--- a/lib/lp/answers/stories/question-reject-and-change-status.txt
409+++ b/lib/lp/answers/stories/question-reject-and-change-status.txt
410@@ -68,7 +68,8 @@ its status is changed to 'Invalid';
411 and the rejection message is added to the question board.
412
413 >>> content = find_main_content(admin_browser.contents)
414- >>> print(content.findAll('div', 'boardCommentBody')[-1].decode_contents())
415+ >>> print(
416+ ... content.find_all('div', 'boardCommentBody')[-1].decode_contents())
417 <p>Rejecting because it's a duplicate of <a...>bug #1</a>.</p>
418
419 The call to help with this problem is not displayed.
420@@ -155,6 +156,7 @@ its status is updated;
421 and the explanation message is added to the question discussion:
422
423 >>> content = find_main_content(admin_browser.contents)
424- >>> print(content.findAll('div', 'boardCommentBody')[-1].decode_contents())
425+ >>> print(
426+ ... content.find_all('div', 'boardCommentBody')[-1].decode_contents())
427 <p>Setting status back to 'Open'. Questions similar to a
428 bug report should be linked to it, not rejected.</p>
429diff --git a/lib/lp/answers/stories/question-search-multiple-languages.txt b/lib/lp/answers/stories/question-search-multiple-languages.txt
430index e83655f..aaa1ccc 100644
431--- a/lib/lp/answers/stories/question-search-multiple-languages.txt
432+++ b/lib/lp/answers/stories/question-search-multiple-languages.txt
433@@ -20,7 +20,7 @@ information.
434
435 >>> anon_browser.open('http://launchpad.test/distros/ubuntu/+questions')
436 >>> soup = find_main_content(anon_browser.contents)
437- >>> for question in soup.findAll('td', 'questionTITLE'):
438+ >>> for question in soup.find_all('td', 'questionTITLE'):
439 ... print(question.find('a').decode_contents())
440 Continue playing after shutdown
441 Play DVDs in Totem
442@@ -31,7 +31,7 @@ information.
443 # Since we have more than 5 results, some of them are in the second batch.
444 >>> anon_browser.getLink('Next').click()
445 >>> soup = find_main_content(anon_browser.contents)
446- >>> for question in soup.findAll('td', 'questionTITLE'):
447+ >>> for question in soup.find_all('td', 'questionTITLE'):
448 ... print(question.find('a').decode_contents())
449 Installation failed
450
451@@ -50,7 +50,7 @@ the anonymous user will see a Spanish question.
452 >>> anon_browser.getControl('English (en)').selected = False
453 >>> anon_browser.getControl('Search', index=0).click()
454 >>> table = find_tag_by_id(anon_browser.contents, 'question-listing')
455- >>> for question in table.findAll('td', 'questionTITLE'):
456+ >>> for question in table.find_all('td', 'questionTITLE'):
457 ... print(question.find('a').decode_contents())
458 Problema al recompilar kernel con soporte smp (doble-núcleo)
459 Continue playing after shutdown
460@@ -62,7 +62,7 @@ While the user might recognize the first question above is in Spanish,
461 browsers and search engine robots need help. Each row in the list
462 of questions declares its language and text direction.
463
464- >>> for question in table.findAll('tr', lang=True):
465+ >>> for question in table.find_all('tr', lang=True):
466 ... print('lang="%s" dir="%s"' % (question['lang'], question['dir']))
467 lang="es" dir="ltr"
468 lang="en" dir="ltr"
469@@ -76,13 +76,13 @@ Arabic and is written from right-to-left.
470
471 >>> anon_browser.getLink('Next').click()
472 >>> table = find_tag_by_id(anon_browser.contents, 'question-listing')
473- >>> for question in table.findAll('td', 'questionTITLE'):
474+ >>> for question in table.find_all('td', 'questionTITLE'):
475 ... print(question.find('a').decode_contents())
476 Slow system
477 Installation failed
478 عكس ...
479
480- >>> for question in table.findAll('tr', lang=True):
481+ >>> for question in table.find_all('tr', lang=True):
482 ... print('lang="%s" dir="%s"' % (question['lang'], question['dir']))
483 lang="en" dir="ltr"
484 lang="en" dir="ltr"
485@@ -137,7 +137,7 @@ then questions with those language will be displayed:
486 True
487
488 >>> soup = find_main_content(anon_browser.contents)
489- >>> for question in soup.findAll('td', 'questionTITLE'):
490+ >>> for question in soup.find_all('td', 'questionTITLE'):
491 ... print(question.find('a').decode_contents())
492 Problema al recompilar kernel con soporte smp (doble-núcleo)
493 Continue playing after shutdown
494@@ -148,7 +148,7 @@ then questions with those language will be displayed:
495 # Since we have more than 5 results, some of them are in the second batch.
496 >>> anon_browser.getLink('Next').click()
497 >>> soup = find_main_content(anon_browser.contents)
498- >>> for question in soup.findAll('td', 'questionTITLE'):
499+ >>> for question in soup.find_all('td', 'questionTITLE'):
500 ... print(question.find('a').decode_contents())
501 Slow system
502 Installation failed
503@@ -212,7 +212,7 @@ the search results.
504 >>> browser.getControl('English (en)').selected = False
505 >>> browser.getControl('Search', index=0).click()
506 >>> content = find_main_content(browser.contents)
507- >>> for question in content.findAll('td', 'questionTITLE'):
508+ >>> for question in content.find_all('td', 'questionTITLE'):
509 ... print(question.find('a').decode_contents())
510 Problema al recompilar kernel con soporte smp (doble-núcleo)
511
512@@ -252,7 +252,7 @@ English, and can use it to locate English questions.
513 >>> daf_browser.getControl('English (en)').selected = True
514 >>> daf_browser.getControl('Search', index=0).click()
515 >>> content = find_main_content(daf_browser.contents)
516- >>> for question in content.findAll('td', 'questionTITLE'):
517+ >>> for question in content.find_all('td', 'questionTITLE'):
518 ... print(question.find('a').decode_contents())
519 Continue playing after shutdown
520 Play DVDs in Totem
521@@ -301,7 +301,7 @@ the preceding page.
522 ['Open']
523
524 >>> content = find_main_content(user_browser.contents)
525- >>> for question in content.findAll('td', 'questionTITLE'):
526+ >>> for question in content.find_all('td', 'questionTITLE'):
527 ... print(question.find('a').decode_contents())
528 Problemas de Impressão no Firefox
529
530@@ -330,7 +330,7 @@ project. They can see the question on the second page of "My questions"...
531 lang: ar
532 dir: rtl
533
534- >>> for question in questions.findAll('td', {'class': 'questionTITLE'}):
535+ >>> for question in questions.find_all('td', {'class': 'questionTITLE'}):
536 ... print(question.find('a').decode_contents())
537 عكس التغ...
538
539diff --git a/lib/lp/answers/stories/question-workflow.txt b/lib/lp/answers/stories/question-workflow.txt
540index 08de35a..984aaf4 100755
541--- a/lib/lp/answers/stories/question-workflow.txt
542+++ b/lib/lp/answers/stories/question-workflow.txt
543@@ -22,7 +22,7 @@ the Firefox product which was filed by 'Sample Person'.
544
545 >>> def find_last_comment(contents):
546 ... soup = find_main_content(contents)
547- ... return soup.findAll('div', 'boardCommentBody')[-1]
548+ ... return soup.find_all('div', 'boardCommentBody')[-1]
549
550 >>> def print_last_comment(contents):
551 ... print(extract_text(find_last_comment(contents)))
552@@ -179,7 +179,7 @@ When the owner comes back on the question page, they will now see a new
553 >>> owner_browser.open(
554 ... 'http://launchpad.test/firefox/+question/2')
555 >>> soup = find_main_content(owner_browser.contents)
556- >>> soup.findAll('div', 'boardComment')[-1].find('input', type='submit')
557+ >>> soup.find_all('div', 'boardComment')[-1].find('input', type='submit')
558 <input name="field.actions.confirm" type="submit"
559 value="This Solved My Problem"/>
560
561@@ -214,7 +214,7 @@ confirmation message was appended to the question discussion:
562 The confirmed answer is also highlighted.
563
564 >>> soup = find_main_content(owner_browser.contents)
565- >>> bestAnswer = soup.findAll('div', 'boardComment')[-2]
566+ >>> bestAnswer = soup.find_all('div', 'boardComment')[-2]
567 >>> print(bestAnswer.find('img'))
568 <img ... src="/@@/favourite-yes" ... title="Marked as best answer"/>
569
570@@ -285,7 +285,7 @@ This also removes the highlighting from the previous answer and sets the
571 answerer back to None.
572
573 >>> soup = find_main_content(owner_browser.contents)
574- >>> bestAnswer = soup.findAll('div', 'boardComment')[-4]
575+ >>> bestAnswer = soup.find_all('div', 'boardComment')[-4]
576 >>> bestAnswer.find('strong') is None
577 True
578
579@@ -332,7 +332,7 @@ A message is displayed to the user confirming that the question is
580 solved and suggesting that the user choose an answer that helped the
581 question owner to solve their problem.
582
583- >>> for message in soup.findAll('div', 'informational message'):
584+ >>> for message in soup.find_all('div', 'informational message'):
585 ... print(extract_text(message))
586 Your question is solved. If a particular message helped you solve the
587 problem, use the 'This solved my problem' button.
588@@ -382,15 +382,15 @@ It lists all the actions performed through workflow on the question:
589
590 >>> soup = find_main_content(anon_browser.contents)
591 >>> action_listing = soup.find('table', 'listing')
592- >>> for header in action_listing.findAll('th'):
593+ >>> for header in action_listing.find_all('th'):
594 ... print(header.decode_contents())
595 When
596 Who
597 Action
598 New State
599
600- >>> for row in action_listing.find('tbody').findAll('tr'):
601- ... cells = row.findAll('td')
602+ >>> for row in action_listing.find('tbody').find_all('tr'):
603+ ... cells = row.find_all('td')
604 ... who = extract_text(cells[1].find('a'))
605 ... action = cells[2].decode_contents()
606 ... new_status = cells[3].decode_contents()
607@@ -435,7 +435,7 @@ choosing an answer that helped him solve his problem.
608 Status: Solved ...
609
610 >>> content = find_main_content(carlos_browser.contents)
611- >>> messages = content.findAll('div', 'informational message')
612+ >>> messages = content.find_all('div', 'informational message')
613 >>> messages
614 []
615
616diff --git a/lib/lp/answers/stories/questions-index.txt b/lib/lp/answers/stories/questions-index.txt
617index 3285409..99969d7 100644
618--- a/lib/lp/answers/stories/questions-index.txt
619+++ b/lib/lp/answers/stories/questions-index.txt
620@@ -26,7 +26,7 @@ It shows the 5 latest questions asked:
621 ... anon_browser.contents, 'latest-questions-asked')
622 >>> print(latest_questions_asked.find('h2').decode_contents())
623 Latest questions asked
624- >>> for row in latest_questions_asked.findAll('li'):
625+ >>> for row in latest_questions_asked.find_all('li'):
626 ... print(row.find('a').decode_contents())
627 13: Problemas de Impressão no Firefox
628 12: Problema al recompilar kernel con soporte smp (doble-núcleo)
629@@ -40,7 +40,7 @@ As well as the 5 latest questions solved:
630 ... anon_browser.contents, 'latest-questions-solved')
631 >>> print(latest_questions_solved.find('h2').decode_contents())
632 Latest questions solved
633- >>> for row in latest_questions_solved.findAll('li'):
634+ >>> for row in latest_questions_solved.find_all('li'):
635 ... print(row.find('a').decode_contents())
636 9: mailto: problem in webpage
637
638diff --git a/lib/lp/answers/stories/this-is-a-faq.txt b/lib/lp/answers/stories/this-is-a-faq.txt
639index 56168bf..3164116 100644
640--- a/lib/lp/answers/stories/this-is-a-faq.txt
641+++ b/lib/lp/answers/stories/this-is-a-faq.txt
642@@ -51,7 +51,7 @@ no FAQ is associated to the question, the 'No existing FAQs are
643 relevant' option is selected.
644
645 >>> def printFAQOptions(contents):
646- ... buttons = find_main_content(contents).findAll(
647+ ... buttons = find_main_content(contents).find_all(
648 ... 'input', {'name': 'field.faq'})
649 ... for button in buttons:
650 ... label = extract_text(button.parent)
651@@ -60,7 +60,7 @@ relevant' option is selected.
652 ... else:
653 ... radio = '( )'
654 ... if button['value']:
655- ... link = button.findNext('a').decode_contents()
656+ ... link = button.find_next('a').decode_contents()
657 ... else:
658 ... link = ''
659 ... print(radio, label, link)
660diff --git a/lib/lp/answers/tests/test_question_webservice.py b/lib/lp/answers/tests/test_question_webservice.py
661index 1dd2e42..e36d199 100644
662--- a/lib/lp/answers/tests/test_question_webservice.py
663+++ b/lib/lp/answers/tests/test_question_webservice.py
664@@ -110,7 +110,7 @@ class TestQuestionRepresentation(TestCaseWithFactory):
665 """Find the question title field in an XHTML document fragment."""
666 soup = BeautifulSoup(response.body)
667 dt = soup.find('dt', text="title")
668- dd = dt.findNextSibling('dd')
669+ dd = dt.find_next_sibling('dd')
670 return str(dd.contents.pop())
671
672 def test_top_level_question_get(self):
673diff --git a/lib/lp/app/browser/doc/base-layout.txt b/lib/lp/app/browser/doc/base-layout.txt
674index f9eb8b7..f091fc9 100644
675--- a/lib/lp/app/browser/doc/base-layout.txt
676+++ b/lib/lp/app/browser/doc/base-layout.txt
677@@ -140,7 +140,7 @@ Page Footers
678 >>> bugs_request.setPrincipal(user)
679 >>> view = BugsMainSideView(user, bugs_request)
680 >>> footer = find_tag_by_id(html, 'footer')
681- >>> for tag in footer.findAll('a'):
682+ >>> for tag in footer.find_all('a'):
683 ... print(tag.string, tag['href'])
684 None http://launchpad.test/
685 Take the tour http://launchpad.test/+tour
686diff --git a/lib/lp/app/browser/tests/test_launchpadroot.py b/lib/lp/app/browser/tests/test_launchpadroot.py
687index ece132e..f51ef2b 100644
688--- a/lib/lp/app/browser/tests/test_launchpadroot.py
689+++ b/lib/lp/app/browser/tests/test_launchpadroot.py
690@@ -179,7 +179,7 @@ class LaunchpadRootIndexViewTestCase(TestCaseWithFactory):
691 markup = BeautifulSoup(
692 result, parse_only=SoupStrainer(id='homepage-blogposts'))
693 self.assertEqual(['called'], calls)
694- items = markup.findAll('li', 'news')
695+ items = markup.find_all('li', 'news')
696 # Notice about launchpad being opened is always added at the end
697 self.assertEqual(3, len(items))
698 a = items[-1].find("a")
699@@ -226,7 +226,7 @@ class LaunchpadRootIndexViewTestCase(TestCaseWithFactory):
700 result = view()
701 markup = BeautifulSoup(
702 result, parse_only=SoupStrainer(id='homepage-blogposts'))
703- items = markup.findAll('li', 'news')
704+ items = markup.find_all('li', 'news')
705 self.assertEqual(3, len(items))
706
707 def test_featured_projects_query_count(self):
708diff --git a/lib/lp/app/doc/hierarchical-menu.txt b/lib/lp/app/doc/hierarchical-menu.txt
709index e9f411e..380d1bb 100644
710--- a/lib/lp/app/doc/hierarchical-menu.txt
711+++ b/lib/lp/app/doc/hierarchical-menu.txt
712@@ -254,7 +254,7 @@ location bar.
713 # Borrowed from lp.testing.pages.print_location()
714 >>> def print_hierarchy(html):
715 ... soup = BeautifulSoup(html)
716- ... hierarchy = soup.find(attrs={'class': 'breadcrumbs'}).findAll(
717+ ... hierarchy = soup.find(attrs={'class': 'breadcrumbs'}).find_all(
718 ... recursive=False)
719 ... segments = [extract_text(step) for step in hierarchy]
720 ... print('Location:', ' > '.join(segments))
721diff --git a/lib/lp/app/doc/launchpadform.txt b/lib/lp/app/doc/launchpadform.txt
722index e02851b..e79a5ec 100644
723--- a/lib/lp/app/doc/launchpadform.txt
724+++ b/lib/lp/app/doc/launchpadform.txt
725@@ -491,7 +491,7 @@ By default, all widgets are visible.
726
727 >>> from lp.services.beautifulsoup import BeautifulSoup
728 >>> soup = BeautifulSoup(view())
729- >>> for input in soup.findAll('input'):
730+ >>> for input in soup.find_all('input'):
731 ... print(input)
732 <input ... name="field.displayname" ... type="text" ...
733
734@@ -505,7 +505,7 @@ using its hidden() method, which should return a hidden <input> tag.
735 >>> view = TestWidgetVisibility2(context, request)
736
737 >>> soup = BeautifulSoup(view())
738- >>> for input in soup.findAll('input'):
739+ >>> for input in soup.find_all('input'):
740 ... print(input)
741 <input ... name="field.displayname" type="hidden" ...
742
743diff --git a/lib/lp/app/doc/tales.txt b/lib/lp/app/doc/tales.txt
744index a6b31fe..0d56ac6 100644
745--- a/lib/lp/app/doc/tales.txt
746+++ b/lib/lp/app/doc/tales.txt
747@@ -670,7 +670,7 @@ size), plus extra links for the MD5 hash and signature of that PRF.
748 >>> from lp.services.beautifulsoup import BeautifulSoup
749 >>> def print_hrefs_with_titles(html):
750 ... soup = BeautifulSoup(html)
751- ... for link in soup.findAll('a'):
752+ ... for link in soup.find_all('a'):
753 ... attrs = dict(link.attrs)
754 ... print("%s: %s" % (attrs.get('href'), attrs.get('title', '')))
755
756diff --git a/lib/lp/app/stories/launchpad-root/xx-featuredprojects.txt b/lib/lp/app/stories/launchpad-root/xx-featuredprojects.txt
757index 2ca6482..bf0dd16 100644
758--- a/lib/lp/app/stories/launchpad-root/xx-featuredprojects.txt
759+++ b/lib/lp/app/stories/launchpad-root/xx-featuredprojects.txt
760@@ -33,7 +33,7 @@ projects' pages in Launchpad. The "project of the day" is listed separately.
761 GNOME
762
763 >>> featured_list = featured.find('', 'featured-projects-list')
764- >>> for link in featured_list.findAll('a'):
765+ >>> for link in featured_list.find_all('a'):
766 ... print(extract_text(link))
767 Gnome Applets
768 Bazaar
769@@ -100,7 +100,7 @@ is now at index '4' and is therefore displayed as the top project:
770 Gentoo
771
772 >>> featured_list = featured.find('', 'featured-projects-list')
773- >>> for link in featured_list.findAll('a'):
774+ >>> for link in featured_list.find_all('a'):
775 ... print(extract_text(link))
776 Apache
777 Gnome Applets
778@@ -128,7 +128,7 @@ that Apache has been removed:
779
780 >>> anon_browser.open('http://launchpad.test/')
781 >>> featured = find_tag_by_id(anon_browser.contents, 'homepage-featured')
782- >>> for link in featured.findAll('a'):
783+ >>> for link in featured.find_all('a'):
784 ... print(extract_text(link))
785 GNOME
786 Gnome Applets
787diff --git a/lib/lp/app/widgets/doc/launchpad-radio-widget.txt b/lib/lp/app/widgets/doc/launchpad-radio-widget.txt
788index ac23c43..017d69d 100644
789--- a/lib/lp/app/widgets/doc/launchpad-radio-widget.txt
790+++ b/lib/lp/app/widgets/doc/launchpad-radio-widget.txt
791@@ -24,7 +24,7 @@ The widget is rendered as a collection of labels with the radio
792 buttons inside.
793
794 >>> html = BeautifulSoup(radio_widget())
795- >>> for label in html.findAll('label'):
796+ >>> for label in html.find_all('label'):
797 ... print(label.decode_contents(formatter='html'))
798 <input checked="checked" class="radioType" id="field.branch_type.0"
799 name="field.branch_type" type="radio" value="HOSTED"/>&nbsp;Hosted
800diff --git a/lib/lp/app/widgets/tests/test_launchpadtarget.py b/lib/lp/app/widgets/tests/test_launchpadtarget.py
801index 147e44d..13030cd 100644
802--- a/lib/lp/app/widgets/tests/test_launchpadtarget.py
803+++ b/lib/lp/app/widgets/tests/test_launchpadtarget.py
804@@ -318,6 +318,6 @@ class LaunchpadTargetWidgetTestCase(TestCaseWithFactory):
805 'field.target.product',
806 ]
807 soup = BeautifulSoup(markup)
808- fields = soup.findAll(['input', 'select'], {'id': re.compile('.*')})
809+ fields = soup.find_all(['input', 'select'], {'id': re.compile('.*')})
810 ids = [field['id'] for field in fields]
811 self.assertContentEqual(expected_ids, ids)
812diff --git a/lib/lp/blueprints/browser/tests/test_person_upcomingwork.py b/lib/lp/blueprints/browser/tests/test_person_upcomingwork.py
813index 8aa2365..e5c79b2 100644
814--- a/lib/lp/blueprints/browser/tests/test_person_upcomingwork.py
815+++ b/lib/lp/blueprints/browser/tests/test_person_upcomingwork.py
816@@ -296,7 +296,7 @@ class TestPersonUpcomingWork(BrowserTestCase):
817 groups = find_tags_by_class(browser.contents, 'collapsible-body')
818 self.assertEqual(1, len(groups))
819 tbody = groups[0]
820- title_td = tbody.findChildren('td')[0]
821+ title_td = tbody.find_all('td')[0]
822 self.assertEqual(
823 "<td>\n<span>&lt;script&gt;window.alert('XSS')&lt;/script&gt;"
824 "</span>\n</td>", str(title_td))
825diff --git a/lib/lp/blueprints/stories/sprints/sprint-settopics.txt b/lib/lp/blueprints/stories/sprints/sprint-settopics.txt
826index 9bf8a84..9598918 100644
827--- a/lib/lp/blueprints/stories/sprints/sprint-settopics.txt
828+++ b/lib/lp/blueprints/stories/sprints/sprint-settopics.txt
829@@ -58,7 +58,7 @@ First choose a driver for the UDS Guacamole sprint.
830 'http://launchpad.test/sprints/uds-guacamole'
831
832 >>> meeting_drivers = find_tag_by_id(browser.contents, 'meeting-drivers')
833- >>> print(extract_text(meeting_drivers.findNext('a')))
834+ >>> print(extract_text(meeting_drivers.find_next('a')))
835 Ubuntu Team
836
837 Any member of the Ubuntu-Team can now approve and/or decline items to the UDS
838diff --git a/lib/lp/blueprints/stories/sprints/xx-sprint-meeting-export.txt b/lib/lp/blueprints/stories/sprints/xx-sprint-meeting-export.txt
839index f9e2b34..2351560 100644
840--- a/lib/lp/blueprints/stories/sprints/xx-sprint-meeting-export.txt
841+++ b/lib/lp/blueprints/stories/sprints/xx-sprint-meeting-export.txt
842@@ -33,7 +33,7 @@ The attendees element contains a list of person elements.
843 >>> import operator
844 >>> from lp.services.beautifulsoup import BeautifulSoup
845 >>> soup = BeautifulSoup(browser.contents, 'xml')
846- >>> people = soup.find('attendees').findAll('person')
847+ >>> people = soup.find('attendees').find_all('person')
848 >>> for person in sorted(people, key=operator.itemgetter("displayname")):
849 ... print("%(displayname)s, %(name)s, %(start)s -> %(end)s" % person)
850 Celso Providelo, cprov, 2005-10-07T23:30:00Z -> 2005-11-17T00:11:00Z
851@@ -43,7 +43,7 @@ The <unscheduled /> element contains a list of meetings. Each of these
852 actually refers to a Specification.
853
854 >>> soup = BeautifulSoup(browser.contents, 'xml')
855- >>> meetings = soup.find('unscheduled').findAll('meeting')
856+ >>> meetings = soup.find('unscheduled').find_all('meeting')
857 >>> for meeting in meetings:
858 ... print("%(id)s: %(name)s, %(lpurl)s" % meeting)
859 3: svg-support, .../+spec/svg-support
860diff --git a/lib/lp/blueprints/stories/sprints/xx-sprints.txt b/lib/lp/blueprints/stories/sprints/xx-sprints.txt
861index f826a65..0068d91 100644
862--- a/lib/lp/blueprints/stories/sprints/xx-sprints.txt
863+++ b/lib/lp/blueprints/stories/sprints/xx-sprints.txt
864@@ -266,7 +266,7 @@ We should be able to see the workload of a sprint:
865 We should be able to see the spec assignment table of a sprint:
866
867 >>> mainarea = find_main_content(anon_browser.contents)
868- >>> for header in mainarea.findAll('th'):
869+ >>> for header in mainarea.find_all('th'):
870 ... print(header.decode_contents())
871 Priority
872 Name
873@@ -381,7 +381,7 @@ Now, Sample Person should be listed as an attendee.
874 >>> def print_attendees(sprint_page):
875 ... """Print the attendees listed in the attendees portlet."""
876 ... attendees_portlet = find_portlet(sprint_page, 'Attendees')
877- ... for li in attendees_portlet.findAll('ul')[0].findAll('li'):
878+ ... for li in attendees_portlet.find_all('ul')[0].find_all('li'):
879 ... print(li.a.string)
880
881 >>> print_attendees(browser.contents)
882diff --git a/lib/lp/blueprints/stories/standalone/subscribing.txt b/lib/lp/blueprints/stories/standalone/subscribing.txt
883index 9116856..f3feaef 100644
884--- a/lib/lp/blueprints/stories/standalone/subscribing.txt
885+++ b/lib/lp/blueprints/stories/standalone/subscribing.txt
886@@ -166,7 +166,7 @@ based on the subscription change we have made above.
887
888 >>> subscribers = find_tags_by_class(browser.contents, 'subscriber')
889 >>> for subscriber in subscribers:
890- ... a_tags = subscriber.findAll('a')
891+ ... a_tags = subscriber.find_all('a')
892 ... img = a_tags[0].find('img')
893 ... print(img['src'], end=' ')
894 ... print(a_tags[1].string)
895@@ -191,7 +191,7 @@ based on the subscription change we have made above.
896
897 >>> subscribers = find_tags_by_class(browser.contents, 'subscriber')
898 >>> for subscriber in subscribers:
899- ... a_tags = subscriber.findAll('a')
900+ ... a_tags = subscriber.find_all('a')
901 ... img = a_tags[0].find('img')
902 ... print(img['src'], end=' ')
903 ... print(a_tags[1].string)
904@@ -324,7 +324,7 @@ not.
905 ... "http://blueprints.launchpad.test/firefox/+spec/svg-support")
906 >>> subscribers = find_tags_by_class(browser.contents, 'subscriber')
907 >>> for subscriber in subscribers:
908- ... a_tags = subscriber.findAll('a')
909+ ... a_tags = subscriber.find_all('a')
910 ... img = a_tags[0].find('img')
911 ... print(img['src'], end=' ')
912 ... print(a_tags[1].string)
913diff --git a/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py b/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
914index 9468505..c80a5e9 100644
915--- a/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
916+++ b/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
917@@ -269,7 +269,7 @@ class TestBugTargetFileBugConfirmationMessage(TestCaseWithFactory):
918 main_content = find_main_content(html)
919 filebug_form = main_content.find(id='filebug-form')
920 self.assertIsNot(None, filebug_form)
921- filebug_form_container = filebug_form.findParents(
922+ filebug_form_container = filebug_form.find_parents(
923 id='filebug-form-container')[0]
924 class_attrs = [item.strip()
925 for item in filebug_form_container['class']]
926diff --git a/lib/lp/bugs/browser/tests/test_bugtask.py b/lib/lp/bugs/browser/tests/test_bugtask.py
927index 075bf72..c71af4f 100644
928--- a/lib/lp/bugs/browser/tests/test_bugtask.py
929+++ b/lib/lp/bugs/browser/tests/test_bugtask.py
930@@ -1120,7 +1120,7 @@ class TestBugTaskDeleteView(TestCaseWithFactory):
931 view.request.response.getHeader('content-type'), 'text/html')
932 table = find_tag_by_id(result_html, 'affected-software')
933 self.assertIsNotNone(table)
934- [row] = table.tbody.findAll('tr', {'class': 'highlight'})
935+ [row] = table.tbody.find_all('tr', {'class': 'highlight'})
936 target_link = row.find('a', {'class': 'sprite product'})
937 self.assertIn(
938 bug.default_bugtask.bugtargetdisplayname, target_link)
939diff --git a/lib/lp/bugs/externalbugtracker/mantis.py b/lib/lp/bugs/externalbugtracker/mantis.py
940index 6673378..c3257a5 100644
941--- a/lib/lp/bugs/externalbugtracker/mantis.py
942+++ b/lib/lp/bugs/externalbugtracker/mantis.py
943@@ -359,7 +359,7 @@ class Mantis(ExternalBugTracker):
944 and not isinstance(node, Comment)))
945 if app_error:
946 app_error_code = ''.join(c for c in app_error if c.isdigit())
947- app_error_message = app_error.findNext('p')
948+ app_error_message = app_error.find_next('p')
949 if app_error_message is not None:
950 app_error_message = app_error_message.string
951 return app_error_code, app_error_message
952@@ -388,7 +388,7 @@ class Mantis(ExternalBugTracker):
953 if key_node is None:
954 raise UnparsableBugData("Key %r not found." % (key,))
955
956- value_cell = key_node.findNext('td')
957+ value_cell = key_node.find_next('td')
958 if value_cell is None:
959 raise UnparsableBugData(
960 "Value cell for key %r not found." % (key,))
961diff --git a/lib/lp/bugs/externalbugtracker/sourceforge.py b/lib/lp/bugs/externalbugtracker/sourceforge.py
962index 1d259c8..41b83dc 100644
963--- a/lib/lp/bugs/externalbugtracker/sourceforge.py
964+++ b/lib/lp/bugs/externalbugtracker/sourceforge.py
965@@ -61,7 +61,7 @@ class SourceForge(ExternalBugTracker):
966 # Happily, BeautifulSoup will turn the contents of this tag
967 # into a newline-delimited list from which we can then
968 # extract the requisite data.
969- status_row = status_tag.findParent().findParent()
970+ status_row = status_tag.find_parent().find_parent()
971 status = status_row.contents[-1]
972 status = status.strip()
973 else:
974@@ -84,7 +84,7 @@ class SourceForge(ExternalBugTracker):
975 # find it it's not critical.
976 resolution_tag = soup.find(text=re.compile('Resolution:'))
977 if resolution_tag:
978- resolution_row = resolution_tag.findParent().findParent()
979+ resolution_row = resolution_tag.find_parent().find_parent()
980 resolution = resolution_row.contents[-1]
981 resolution = resolution.strip()
982 else:
983diff --git a/lib/lp/bugs/scripts/bzremotecomponentfinder.py b/lib/lp/bugs/scripts/bzremotecomponentfinder.py
984index 8286e73..2dac377 100644
985--- a/lib/lp/bugs/scripts/bzremotecomponentfinder.py
986+++ b/lib/lp/bugs/scripts/bzremotecomponentfinder.py
987@@ -80,7 +80,7 @@ class BugzillaRemoteComponentScraper:
988 'versions': None,
989 })
990
991- for script_text in soup.findAll(name="script"):
992+ for script_text in soup.find_all(name="script"):
993 if script_text is None or script_text.string is None:
994 continue
995 for line in script_text.string.split(";"):
996diff --git a/lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt b/lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt
997index 293dc89..3b0f4c5 100644
998--- a/lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt
999+++ b/lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt
1000@@ -506,7 +506,7 @@ But we're happy, so we add the bug watch.
1001 >>> bug_watches = find_portlet(
1002 ... user_browser.contents, 'Remote bug watches')
1003 >>> for li in bug_watches('li'):
1004- ... print(li.findAll('a')[0].decode_contents())
1005+ ... print(li.find_all('a')[0].decode_contents())
1006 gnome-bugzilla #42
1007
1008 It's possible to supply an HTTPS URL, even though the bug tracker's base
1009@@ -532,7 +532,7 @@ The URL was automatically converted to HTTP:
1010 >>> bug_watches = find_portlet(
1011 ... user_browser.contents, 'Remote bug watches')
1012 >>> for li in bug_watches('li'):
1013- ... print(li.findAll('a')[0]['href'])
1014+ ... print(li.find_all('a')[0]['href'])
1015 http://bugzilla.gnome.org/bugs/show_bug.cgi?id=42
1016 http://bugzilla.gnome.org/bugs/show_bug.cgi?id=84
1017
1018@@ -597,7 +597,7 @@ registered automatically.
1019 >>> bug_watches = find_portlet(
1020 ... user_browser.contents, 'Remote bug watches')
1021 >>> for li in bug_watches('li'):
1022- ... print(li.findAll('a')[0].decode_contents())
1023+ ... print(li.find_all('a')[0].decode_contents())
1024 gnome-bugzilla #42
1025 gnome-bugzilla #84
1026 auto-new.trac #42
1027@@ -623,7 +623,7 @@ it to HTTP on their behalf:
1028 >>> bug_watches = find_portlet(
1029 ... user_browser.contents, 'Remote bug watches')
1030 >>> for li in bug_watches('li'):
1031- ... print(li.findAll('a')[0]['href'])
1032+ ... print(li.find_all('a')[0]['href'])
1033 http://bugzilla.gnome.org/bugs/show_bug.cgi?id=168
1034 http://bugzilla.gnome.org/bugs/show_bug.cgi?id=42
1035 http://bugzilla.gnome.org/bugs/show_bug.cgi?id=84
1036diff --git a/lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt b/lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt
1037index 3210e65..9d380cf 100644
1038--- a/lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt
1039+++ b/lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt
1040@@ -20,8 +20,8 @@ Now we can see the added bug watch in the bug watch portlet.
1041
1042 >>> bugwatch_portlet = find_portlet(
1043 ... user_browser.contents, 'Remote bug watches')
1044- >>> for li_tag in bugwatch_portlet.findAll('li'):
1045- ... print(li_tag.findAll('a')[0].decode_contents())
1046+ >>> for li_tag in bugwatch_portlet.find_all('li'):
1047+ ... print(li_tag.find_all('a')[0].decode_contents())
1048 debbugs #42
1049
1050 If we add another bug watch, pointing to the same URL, the previous one
1051@@ -46,8 +46,8 @@ will be used; i.e., another one won't be added.
1052
1053 >>> bugwatch_portlet = find_portlet(
1054 ... user_browser.contents, 'Remote bug watches')
1055- >>> for li_tag in bugwatch_portlet.findAll('li'):
1056- ... print(li_tag.findAll('a')[0].string)
1057+ >>> for li_tag in bugwatch_portlet.find_all('li'):
1058+ ... print(li_tag.find_all('a')[0].string)
1059 debbugs #42
1060
1061 Both the thunderbird and gnome-terminal Debian tasks are pointing to the
1062diff --git a/lib/lp/bugs/stories/bug-tags/xx-official-bug-tags.txt b/lib/lp/bugs/stories/bug-tags/xx-official-bug-tags.txt
1063index a64997f..9b3596f 100644
1064--- a/lib/lp/bugs/stories/bug-tags/xx-official-bug-tags.txt
1065+++ b/lib/lp/bugs/stories/bug-tags/xx-official-bug-tags.txt
1066@@ -106,7 +106,7 @@ They are grouped together at the beginning of the list.
1067
1068 >>> browser.open(gfoobar_bug_url)
1069 >>> tags_div = find_tag_by_id(browser.contents, 'bug-tags')
1070- >>> print_bug_tag_anchors(tags_div.findAll('a'))
1071+ >>> print_bug_tag_anchors(tags_div.find_all('a'))
1072 official-tag alpha
1073 official-tag charlie
1074 unofficial-tag bravo
1075diff --git a/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt b/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt
1076index 404810e..564d154 100644
1077--- a/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt
1078+++ b/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt
1079@@ -36,7 +36,7 @@ After we added the attachment, we get redirected to the bug page.
1080 We can check that the attachment is there
1081
1082 >>> attachments = find_portlet(user_browser.contents, 'Bug attachments')
1083- >>> for li_tag in attachments.findAll('li', 'download-attachment'):
1084+ >>> for li_tag in attachments.find_all('li', 'download-attachment'):
1085 ... print(li_tag.a.decode_contents())
1086 Some information
1087
1088@@ -69,7 +69,7 @@ also not necessary to enter a comment in order to add an attachment.
1089 'http://bugs.launchpad.test/firefox/+bug/1'
1090
1091 >>> attachments = find_portlet(user_browser.contents, 'Bug attachments')
1092- >>> for li_tag in attachments.findAll('li', 'download-attachment'):
1093+ >>> for li_tag in attachments.find_all('li', 'download-attachment'):
1094 ... print(li_tag.a.decode_contents())
1095 Some information
1096 bar.txt
1097@@ -146,7 +146,7 @@ listed as an ordinary attachment.
1098 >>> user_browser.url
1099 'http://bugs.launchpad.test/firefox/+bug/1'
1100 >>> attachments = find_portlet(user_browser.contents, 'Bug attachments')
1101- >>> for li_tag in attachments.findAll('li', 'download-attachment'):
1102+ >>> for li_tag in attachments.find_all('li', 'download-attachment'):
1103 ... print(li_tag.a.decode_contents())
1104 Some information
1105 bar.txt
1106@@ -203,7 +203,7 @@ Now we are redirected to the main bug page...
1107 ...and the new attachment is listed as a patch.
1108
1109 >>> patches = find_portlet(user_browser.contents, 'Patches')
1110- >>> for li_tag in patches.findAll('li', 'download-attachment'):
1111+ >>> for li_tag in patches.find_all('li', 'download-attachment'):
1112 ... print(li_tag.a.decode_contents())
1113 A fix for this bug.
1114 A better icon for foo
1115@@ -331,7 +331,7 @@ Now we are redirected to the main bug page...
1116 "Patches"...
1117
1118 >>> patches = find_portlet(user_browser.contents, 'Patches')
1119- >>> for li_tag in patches.findAll('li', 'download-attachment'):
1120+ >>> for li_tag in patches.find_all('li', 'download-attachment'):
1121 ... print(li_tag.a.decode_contents())
1122 Another title
1123 A fix for this bug.
1124@@ -343,7 +343,7 @@ Now we are redirected to the main bug page...
1125 ...while it is gone from the portlet "Bug attachments".
1126
1127 >>> attachments = find_portlet(user_browser.contents, 'Bug attachments')
1128- >>> for li_tag in attachments.findAll('li', 'download-attachment'):
1129+ >>> for li_tag in attachments.find_all('li', 'download-attachment'):
1130 ... print(li_tag.a.decode_contents())
1131 bar.txt
1132 More data
1133diff --git a/lib/lp/bugs/stories/bugattachments/xx-delete-bug-attachment.txt b/lib/lp/bugs/stories/bugattachments/xx-delete-bug-attachment.txt
1134index 459a548..f705c8a 100644
1135--- a/lib/lp/bugs/stories/bugattachments/xx-delete-bug-attachment.txt
1136+++ b/lib/lp/bugs/stories/bugattachments/xx-delete-bug-attachment.txt
1137@@ -17,7 +17,7 @@ The attachment is now visible on the bug page.
1138 >>> user_browser.open('http://launchpad.test/bugs/2')
1139 >>> attachment_portlet = find_portlet(
1140 ... user_browser.contents, 'Bug attachments')
1141- >>> for li in attachment_portlet.findAll('li', 'download-attachment'):
1142+ >>> for li in attachment_portlet.find_all('li', 'download-attachment'):
1143 ... print(li.a.decode_contents())
1144 Great deal
1145
1146diff --git a/lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt b/lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt
1147index 6bd8170..0bc014c 100644
1148--- a/lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt
1149+++ b/lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt
1150@@ -123,7 +123,7 @@ email addresses in messages.
1151 Bug #2 (blackhole) ... : Bugs : Tomcat
1152 >>> text = find_tags_by_class(
1153 ... user_browser.contents, 'boardCommentBody')[-1]
1154- >>> print(extract_text(text.findAll('p')[-2]))
1155+ >>> print(extract_text(text.find_all('p')[-2]))
1156 --
1157 ______________________
1158 human@example.org
1159@@ -138,7 +138,7 @@ unauthenticated, so they will see the obfuscated email address.
1160 Bug #2 (blackhole) ... : Bugs : Tomcat
1161 >>> text = find_tags_by_class(
1162 ... anon_browser.contents, 'boardCommentBody')[-1]
1163- >>> print(extract_text(text.findAll('p')[-2]))
1164+ >>> print(extract_text(text.find_all('p')[-2]))
1165 --
1166 ______________________
1167 &lt;email address hidden&gt;
1168@@ -155,7 +155,7 @@ class.
1169 Pagetests cannot test CSS and JS behaviour. We can only check that the markup
1170 includes the hooks for the style and script.
1171
1172- >>> print(text.findAll('p')[-2])
1173+ >>> print(text.find_all('p')[-2])
1174 <p><span class="foldable">--...
1175 &lt;email address hidden&gt;<br/>
1176 Witty signatures rock!
1177@@ -169,7 +169,7 @@ are wrapped with a tag of 'foldable' class, citation lines are
1178 always displayed. Again we can continue with the anonymous user to
1179 see the markup.
1180
1181- >>> print(text.findAll('p')[-3])
1182+ >>> print(text.find_all('p')[-3])
1183 <p>Somebody said sometime ago:<br/>
1184 <span class="foldable-quoted">
1185 &gt; 1. Remove the letters c, j, q, x, w<br/>
1186@@ -181,12 +181,12 @@ PGP blocks in signed messages are identified by a paragraph that
1187 starts with '-----BEGIN PGP'. There are two kinds of PGP blocks,
1188 the notice that the message is signed, and the signature.
1189
1190- >>> print(text.findAll('p')[0])
1191+ >>> print(text.find_all('p')[0])
1192 <p><span class="foldable">-----BEGIN PGP SIGNED MESSAGE-----<br/>
1193 Hash: SHA1
1194 </span></p>
1195
1196- >>> print(text.findAll('p')[-1])
1197+ >>> print(text.find_all('p')[-1])
1198 <p><span class="foldable">-----BEGIN PGP SIGNATURE-----<br/>
1199 Version: GnuPG v1.4.1 (GNU/Linux)<br/>
1200 Comment: Using GnuPG with Thunderbird<br/>
1201diff --git a/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt b/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt
1202index 6df5a07..f93df7f 100644
1203--- a/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt
1204+++ b/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt
1205@@ -25,7 +25,7 @@ was supplied (through comments) are 'Incomplete (without response)'.
1206 >>> user_browser.getControl(name='field.status:list').value = (
1207 ... ['INCOMPLETE_WITHOUT_RESPONSE'])
1208 >>> user_browser.getControl('Search', index=1).click()
1209- >>> find_tag_by_id(user_browser.contents, 'bugs-table-listing').findChild('a')
1210+ >>> find_tag_by_id(user_browser.contents, 'bugs-table-listing').find('a')
1211 <a class="bugtitle" href="http://bugs.launchpad.test/jokosher/+bug/11">...</a>
1212
1213 Bugs that have been marked incomplete and for which new information was
1214@@ -62,7 +62,7 @@ They try again to find that bug using the advanced search form.
1215 >>> user_browser.getControl(name='field.status:list').value = (
1216 ... ['INCOMPLETE_WITH_RESPONSE'])
1217 >>> user_browser.getControl('Search', index=1).click()
1218- >>> find_tag_by_id(user_browser.contents, 'bugs-table-listing').findChild('a')
1219+ >>> find_tag_by_id(user_browser.contents, 'bugs-table-listing').find('a')
1220 <a class="bugtitle" href="http://bugs.launchpad.test/jokosher/+bug/11">...</a>
1221
1222 The bug is there, since they supplied new information in a comment. No
1223diff --git a/lib/lp/bugs/stories/bugs/xx-malone-homepage.txt b/lib/lp/bugs/stories/bugs/xx-malone-homepage.txt
1224index e5ac687..71d20ff 100644
1225--- a/lib/lp/bugs/stories/bugs/xx-malone-homepage.txt
1226+++ b/lib/lp/bugs/stories/bugs/xx-malone-homepage.txt
1227@@ -10,7 +10,7 @@ Say hello to Bugs. :)
1228 There are a few related pages linked in a portlet:
1229
1230 >>> related_pages = find_portlet(browser.contents, 'Related pages')
1231- >>> for link in related_pages.findAll('a'):
1232+ >>> for link in related_pages.find_all('a'):
1233 ... print("%s\n --> %s" % (extract_text(link), link.get('href')))
1234 Bug trackers
1235 --> http://bugs.launchpad.test/bugs/bugtrackers
1236diff --git a/lib/lp/bugs/stories/bugs/xx-remote-bug-comments.txt b/lib/lp/bugs/stories/bugs/xx-remote-bug-comments.txt
1237index 874f315..7fa1e82 100644
1238--- a/lib/lp/bugs/stories/bugs/xx-remote-bug-comments.txt
1239+++ b/lib/lp/bugs/stories/bugs/xx-remote-bug-comments.txt
1240@@ -64,7 +64,7 @@ mark the comment as 'awaiting synchronization' until it makes its way
1241 to the remote bug tracker.
1242
1243 >>> activity = new_bug_comment.find(attrs={'class': 'boardCommentActivity'})
1244- >>> print(extract_text(activity.findAll('td')[1]))
1245+ >>> print(extract_text(activity.find_all('td')[1]))
1246 Awaiting synchronization
1247
1248 When the comment is synchronized, it receives a remote comment id, and
1249diff --git a/lib/lp/bugs/stories/bugs/xx-unique-ids-on-bug-page.txt b/lib/lp/bugs/stories/bugs/xx-unique-ids-on-bug-page.txt
1250index 0fec67a..5fc9584 100644
1251--- a/lib/lp/bugs/stories/bugs/xx-unique-ids-on-bug-page.txt
1252+++ b/lib/lp/bugs/stories/bugs/xx-unique-ids-on-bug-page.txt
1253@@ -21,7 +21,7 @@ Still, the ids of the fields are unique.
1254 >>> non_unique_ids = []
1255 >>> found_ids = set()
1256 >>> import re
1257- >>> for tag in soup.findAll(id=re.compile('.+')):
1258+ >>> for tag in soup.find_all(id=re.compile('.+')):
1259 ... if tag['id'] in found_ids:
1260 ... non_unique_ids.append(tag['id'])
1261 ... found_ids.add(tag['id'])
1262diff --git a/lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt b/lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt
1263index 7300d25..2076c5b 100644
1264--- a/lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt
1265+++ b/lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt
1266@@ -205,9 +205,9 @@ We display bug badges for associated branches, specifications, patches, etc.
1267
1268 >>> def names_and_branches(contents):
1269 ... listing = find_tag_by_id(contents, 'bugs-table-listing')
1270- ... for row in listing.findAll(None, {'class': 'buglisting-row'}):
1271+ ... for row in listing.find_all(None, {'class': 'buglisting-row'}):
1272 ... badge_cell = row.find(None, {'class': 'bug-related-icons'})
1273- ... spans = badge_cell.findAll('span')
1274+ ... spans = badge_cell.find_all('span')
1275 ... for span in spans:
1276 ... print(" Badge:", span.get('alt'))
1277
1278diff --git a/lib/lp/bugs/stories/bugtracker/bugtrackers-index.txt b/lib/lp/bugs/stories/bugtracker/bugtrackers-index.txt
1279index 74bc2e2..b3d888d 100644
1280--- a/lib/lp/bugs/stories/bugtracker/bugtrackers-index.txt
1281+++ b/lib/lp/bugs/stories/bugtracker/bugtrackers-index.txt
1282@@ -12,8 +12,8 @@ The page presents a table with all bugtrackers currently registered:
1283
1284 >>> def print_tracker_table(browser):
1285 ... table = find_tag_by_id(browser.contents, 'trackers')
1286- ... for row in table.tbody.findAll('tr'):
1287- ... title, location, linked, type, watches = row.findAll('td')
1288+ ... for row in table.tbody.find_all('tr'):
1289+ ... title, location, linked, type, watches = row.find_all('td')
1290 ... print('------------------------')
1291 ... print('\n'.join([
1292 ... extract_text(title),
1293diff --git a/lib/lp/bugs/stories/bugtracker/xx-bugtracker.txt b/lib/lp/bugs/stories/bugtracker/xx-bugtracker.txt
1294index 44e88a4..1b20aef 100644
1295--- a/lib/lp/bugs/stories/bugtracker/xx-bugtracker.txt
1296+++ b/lib/lp/bugs/stories/bugtracker/xx-bugtracker.txt
1297@@ -664,10 +664,10 @@ Then we can see how logged-in users and anonymous users see the page:
1298
1299 >>> def print_watches(browser):
1300 ... watches = find_tag_by_id(
1301- ... browser.contents, 'latestwatches').tbody.findAll('tr')
1302+ ... browser.contents, 'latestwatches').tbody.find_all('tr')
1303 ... for watch in watches:
1304 ... bug, remote_bug, status, last_checked, next_check = (
1305- ... watch.findAll('td'))
1306+ ... watch.find_all('td'))
1307 ... print(extract_text(bug))
1308 ... print(' --> %s: %s' % (
1309 ... extract_text(remote_bug),
1310diff --git a/lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt b/lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt
1311index f9193ac..a3d31eb 100644
1312--- a/lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt
1313+++ b/lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt
1314@@ -119,8 +119,8 @@ created, instead the old one will be used.
1315 'http://bugs.launchpad.test/debian/+source/mozilla-firefox/+bug/1'
1316
1317 >>> bugwatch_portlet = find_portlet(browser.contents, 'Remote bug watches')
1318- >>> for li_tag in bugwatch_portlet.findAll('li'):
1319- ... print(li_tag.findAll('a')[0].string)
1320+ >>> for li_tag in bugwatch_portlet.find_all('li'):
1321+ ... print(li_tag.find_all('a')[0].string)
1322 mozilla.org #123543
1323 mozilla.org #2000
1324 mozilla.org #42
1325diff --git a/lib/lp/bugs/stories/cve/cve-linking.txt b/lib/lp/bugs/stories/cve/cve-linking.txt
1326index 6524905..bdd98f7 100644
1327--- a/lib/lp/bugs/stories/cve/cve-linking.txt
1328+++ b/lib/lp/bugs/stories/cve/cve-linking.txt
1329@@ -75,7 +75,7 @@ forms. This also provides us with a means to test implicitly that bug
1330
1331 >>> admin_browser.open('http://launchpad.test/bugs/cve/1999-8979')
1332 >>> for form in find_main_content(
1333- ... admin_browser.contents).findAll('form'):
1334+ ... admin_browser.contents).find_all('form'):
1335 ... print(form.decode_contents())
1336
1337 Similarly, there should be no links allowing the user to mark the bug as
1338diff --git a/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt b/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt
1339index 96782f6..2210164 100644
1340--- a/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt
1341+++ b/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt
1342@@ -43,7 +43,7 @@ page, because that page does not include a bug description field.
1343 ... user_browser.contents, 'informational message')[0]))
1344
1345 >>> def print_visible_guidelines(context_path, guidelines):
1346- ... result = guidelines.findParents(id='filebug-form-container')
1347+ ... result = guidelines.find_parents(id='filebug-form-container')
1348 ... style_attrs = []
1349 ... if result:
1350 ... filebug_form_container = result[0]
1351diff --git a/lib/lp/bugs/stories/guided-filebug/xx-displaying-similar-bugs.txt b/lib/lp/bugs/stories/guided-filebug/xx-displaying-similar-bugs.txt
1352index bd092de..b1524d2 100644
1353--- a/lib/lp/bugs/stories/guided-filebug/xx-displaying-similar-bugs.txt
1354+++ b/lib/lp/bugs/stories/guided-filebug/xx-displaying-similar-bugs.txt
1355@@ -10,7 +10,7 @@ duplicates.
1356 >>> def print_similar_bugs(content):
1357 ... bugs_list = find_tags_by_class(content, 'similar-bug')
1358 ... for node in bugs_list:
1359- ... label = node.findAll('label')[0]
1360+ ... label = node.find_all('label')[0]
1361 ... label_class = ' '.join(label['class'])
1362 ... text_lines = [line.strip() for line in
1363 ... extract_text(node).splitlines()]
1364diff --git a/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug.txt b/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug.txt
1365index 167ab3a..f835994 100644
1366--- a/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug.txt
1367+++ b/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug.txt
1368@@ -59,7 +59,7 @@ description.
1369 >>> import re
1370
1371 >>> page_soup = find_main_content(user_browser.contents)
1372- >>> field_labels = page_soup.findAll(
1373+ >>> field_labels = page_soup.find_all(
1374 ... 'label', text=re.compile('Further information'))
1375 >>> for field_label in field_labels:
1376 ... print(extract_text(field_label.parent))
1377diff --git a/lib/lp/bugs/stories/guided-filebug/xx-filebug-attachments.txt b/lib/lp/bugs/stories/guided-filebug/xx-filebug-attachments.txt
1378index 28be58c..4843c14 100644
1379--- a/lib/lp/bugs/stories/guided-filebug/xx-filebug-attachments.txt
1380+++ b/lib/lp/bugs/stories/guided-filebug/xx-filebug-attachments.txt
1381@@ -42,7 +42,7 @@ was attached.
1382 No Privileges Person can see the attachment in the attachments portlet.
1383
1384 >>> attachments = find_portlet(user_browser.contents, 'Bug attachments')
1385- >>> for li_tag in attachments.findAll('li', 'download-attachment'):
1386+ >>> for li_tag in attachments.find_all('li', 'download-attachment'):
1387 ... print(li_tag.a.decode_contents())
1388 A description of the attachment
1389
1390diff --git a/lib/lp/bugs/stories/guided-filebug/xx-product-guided-filebug.txt b/lib/lp/bugs/stories/guided-filebug/xx-product-guided-filebug.txt
1391index f7ca514..1e604c5 100644
1392--- a/lib/lp/bugs/stories/guided-filebug/xx-product-guided-filebug.txt
1393+++ b/lib/lp/bugs/stories/guided-filebug/xx-product-guided-filebug.txt
1394@@ -19,10 +19,10 @@ If no title is entered, the user is asked to supply one.
1395
1396 >>> top_portlet = first_tag_by_class(
1397 ... user_browser.contents, 'top-portlet')
1398- >>> for message in top_portlet.findAll(attrs={'class': 'error message'}):
1399+ >>> for message in top_portlet.find_all(attrs={'class': 'error message'}):
1400 ... print(message.decode_contents())
1401 There is 1 error.
1402- >>> for message in top_portlet.findAll(
1403+ >>> for message in top_portlet.find_all(
1404 ... lambda node: node.attrs.get('class') == ['message']):
1405 ... print(message.decode_contents())
1406 Required input is missing.
1407diff --git a/lib/lp/bugs/stories/standalone/xx-show-distribution-cve-report.txt b/lib/lp/bugs/stories/standalone/xx-show-distribution-cve-report.txt
1408index 2b62bcd..17808ec 100644
1409--- a/lib/lp/bugs/stories/standalone/xx-show-distribution-cve-report.txt
1410+++ b/lib/lp/bugs/stories/standalone/xx-show-distribution-cve-report.txt
1411@@ -8,7 +8,7 @@ distro bugs linked to CVEs.
1412
1413 The report lists the open and closed bugs.
1414
1415- >>> for h2 in main.findAll('h2'):
1416+ >>> for h2 in main.find_all('h2'):
1417 ... print(extract_text(h2))
1418 Open bugs
1419 Resolved bugs
1420@@ -18,7 +18,7 @@ distro, since it's probably too big.
1421
1422 >>> browser.open('http://launchpad.test/ubuntu/+cve')
1423 >>> main = find_main_content(browser.contents)
1424- >>> [extract_text(h2) for h2 in main.findAll('h2')]
1425+ >>> [extract_text(h2) for h2 in main.find_all('h2')]
1426 []
1427
1428 Instead, the links for the specific series reports are shown.
1429@@ -27,7 +27,7 @@ Instead, the links for the specific series reports are shown.
1430 CVE reports in releases of Ubuntu
1431
1432 >>> series_list = main.find('div', 'top-portlet').ul
1433- >>> for li in series_list.findAll('li'):
1434+ >>> for li in series_list.find_all('li'):
1435 ... print(extract_text(li))
1436 Breezy Badger Autotest
1437 Grumpy
1438diff --git a/lib/lp/bugs/stories/standalone/xx-show-distrorelease-cve-report.txt b/lib/lp/bugs/stories/standalone/xx-show-distrorelease-cve-report.txt
1439index 069e840..415d755 100644
1440--- a/lib/lp/bugs/stories/standalone/xx-show-distrorelease-cve-report.txt
1441+++ b/lib/lp/bugs/stories/standalone/xx-show-distrorelease-cve-report.txt
1442@@ -38,7 +38,7 @@ sourcepackage value from the bug listed on the previous report.
1443
1444 >>> browser.open('http://launchpad.test/debian/woody/+cve')
1445 >>> main = find_main_content(browser.contents)
1446- >>> for tr in main.table.tbody.findAll('tr'):
1447+ >>> for tr in main.table.tbody.find_all('tr'):
1448 ... print(extract_text(tr))
1449 Bug #2: Blackhole Trash folder CVE-1999-2345
1450 Debian Woody New (unassigned)
1451diff --git a/lib/lp/bugs/tests/bug.py b/lib/lp/bugs/tests/bug.py
1452index d28fc93..9653159 100644
1453--- a/lib/lp/bugs/tests/bug.py
1454+++ b/lib/lp/bugs/tests/bug.py
1455@@ -82,7 +82,7 @@ def print_bug_affects_table(content, highlighted_only=False):
1456 tr_attrs = {'class': 'highlight'}
1457 else:
1458 tr_attrs = {}
1459- tr_tags = affects_table.tbody.findAll(
1460+ tr_tags = affects_table.tbody.find_all(
1461 'tr', attrs=tr_attrs, recursive=False)
1462 for tr in tr_tags:
1463 if tr.td.table:
1464@@ -98,11 +98,11 @@ def print_remote_bugtasks(content):
1465 For each remote bugtask, print the target and the bugwatch.
1466 """
1467 affects_table = find_tags_by_class(content, 'listing')[0]
1468- for span in affects_table.findAll('span'):
1469+ for span in affects_table.find_all('span'):
1470 for key, value in span.attrs.items():
1471 if 'bug-remote' in value:
1472- target = extract_text(span.findAllPrevious('td')[-2])
1473- print(target, extract_text(span.findNext('a')))
1474+ target = extract_text(span.find_all_previous('td')[-2])
1475+ print(target, extract_text(span.find_next('a')))
1476
1477
1478 def print_bugs_list(content, list_id):
1479@@ -113,7 +113,7 @@ def print_bugs_list(content, list_id):
1480 becomes more elaborate then this function will be the place to
1481 cope with it.
1482 """
1483- bugs_list = find_tag_by_id(content, list_id).findAll(
1484+ bugs_list = find_tag_by_id(content, list_id).find_all(
1485 None, {'class': 'similar-bug'})
1486 for node in bugs_list:
1487 # Also strip zero-width spaces out.
1488@@ -229,13 +229,13 @@ def print_upstream_linking_form(browser):
1489
1490 link_upstream_how_radio_control = browser.getControl(
1491 name='field.link_upstream_how')
1492- link_upstream_how_buttons = soup.findAll(
1493+ link_upstream_how_buttons = soup.find_all(
1494 'input', {'name': 'field.link_upstream_how'})
1495
1496 wrapper = textwrap.TextWrapper(width=65, subsequent_indent=' ')
1497 for button in link_upstream_how_buttons:
1498 # Print the radio button.
1499- label = button.findParent('label')
1500+ label = button.find_parent('label')
1501 if label is None:
1502 label = soup.find('label', {'for': button['id']})
1503 if button.get('value') in link_upstream_how_radio_control.value:
1504@@ -244,7 +244,7 @@ def print_upstream_linking_form(browser):
1505 print(wrapper.fill('( ) %s' % extract_text(label)))
1506 # Print related text field, if found. Assumes that the text
1507 # field is in the same table row as the radio button.
1508- text_field = button.findParent('tr').find('input', {'type': 'text'})
1509+ text_field = button.find_parent('tr').find('input', {'type': 'text'})
1510 if text_field is not None:
1511 text_control = browser.getControl(name=text_field.get('name'))
1512 print(' [%s]' % text_control.value.ljust(10))
1513@@ -291,7 +291,7 @@ def print_bugfilters_portlet_filled(browser, target):
1514 def print_ul(ul):
1515 """Print the data from a list."""
1516 li_content = []
1517- for li in ul.findAll('li'):
1518+ for li in ul.find_all('li'):
1519 li_content.append(extract_text(li))
1520 if len(li_content) > 0:
1521 print('\n'.join(li_content))
1522diff --git a/lib/lp/bugs/tests/test_bugs_webservice.py b/lib/lp/bugs/tests/test_bugs_webservice.py
1523index 099c5ca..fd82656 100644
1524--- a/lib/lp/bugs/tests/test_bugs_webservice.py
1525+++ b/lib/lp/bugs/tests/test_bugs_webservice.py
1526@@ -110,7 +110,7 @@ class TestBugDescriptionRepresentation(TestCaseWithFactory):
1527 """Find the bug description field in an XHTML document fragment."""
1528 soup = BeautifulSoup(response.body)
1529 dt = soup.find('dt', text="description")
1530- dd = dt.findNextSibling('dd')
1531+ dd = dt.find_next_sibling('dd')
1532 return str(dd.contents.pop())
1533
1534 def test_GET_xhtml_representation(self):
1535diff --git a/lib/lp/code/browser/codeimport.py b/lib/lp/code/browser/codeimport.py
1536index dfee026..49c3b3f 100644
1537--- a/lib/lp/code/browser/codeimport.py
1538+++ b/lib/lp/code/browser/codeimport.py
1539@@ -388,7 +388,7 @@ class CodeImportNewView(CodeImportBaseView, CodeImportNameValidationMixin):
1540 # Extract the radio buttons from the rcs_type widget, so we can
1541 # display them separately in the form.
1542 soup = BeautifulSoup(self.widgets['rcs_type']())
1543- fields = soup.findAll('input')
1544+ fields = soup.find_all('input')
1545 [cvs_button, svn_button, git_button, bzr_button,
1546 empty_marker] = [
1547 field for field in fields
1548diff --git a/lib/lp/code/browser/tests/test_branch.py b/lib/lp/code/browser/tests/test_branch.py
1549index b731ac7..2727002 100644
1550--- a/lib/lp/code/browser/tests/test_branch.py
1551+++ b/lib/lp/code/browser/tests/test_branch.py
1552@@ -504,7 +504,7 @@ class TestBranchView(BrowserTestCase):
1553
1554 self.assertTextMatchesExpressionIgnoreWhitespace(expected_text, text)
1555
1556- links = revision_content.findAll('a')
1557+ links = revision_content.find_all('a')
1558 self.assertEqual(mp_url, links[2]['href'])
1559
1560 def test_recent_revisions_with_merge_proposals_and_bug_links(self):
1561@@ -559,7 +559,7 @@ class TestBranchView(BrowserTestCase):
1562
1563 self.assertTextMatchesExpressionIgnoreWhitespace(expected_text, text)
1564
1565- links = revision_content.findAll('a')
1566+ links = revision_content.find_all('a')
1567 self.assertEqual(mp_url, links[2]['href'])
1568 self.assertEqual(branch_url, links[3]['href'])
1569 self.assertEqual(linked_bug_urls[0], links[4]['href'])
1570diff --git a/lib/lp/code/browser/tests/test_gitlisting.py b/lib/lp/code/browser/tests/test_gitlisting.py
1571index e7682fc..14239ad 100644
1572--- a/lib/lp/code/browser/tests/test_gitlisting.py
1573+++ b/lib/lp/code/browser/tests/test_gitlisting.py
1574@@ -82,7 +82,7 @@ class TestTargetGitListingView:
1575 'div', id='default-repository-branches').find('table')
1576 self.assertContentEqual(
1577 ['1.0', 'master', 'with#hash', '\N{SNOWMAN}'],
1578- [link.find(text=True) for link in table.findAll('a')])
1579+ [link.find(text=True) for link in table.find_all('a')])
1580 self.assertEndsWith(
1581 table.find(text="1.0").parent['href'],
1582 "/~foowner/%s/+git/foo/+ref/1.0" % self.target_path)
1583@@ -100,7 +100,7 @@ class TestTargetGitListingView:
1584 ['lp:%s' % self.target_path,
1585 'lp:~random/%s/+git/bar' % self.target_path,
1586 'lp:~contributor/%s' % self.target_path],
1587- [link.find(text=True) for link in table.findAll('a')])
1588+ [link.find(text=True) for link in table.find_all('a')])
1589 self.assertEndsWith(
1590 table.find(
1591 text="lp:~contributor/%s" % self.target_path).parent['href'],
1592@@ -149,7 +149,7 @@ class TestTargetGitListingView:
1593 'div', id='gitrepositories-table-listing').find('table')
1594 self.assertContentEqual(
1595 ['lp:~contributor/%s/+git/foo' % self.target_path],
1596- [link.find(text=True) for link in table.findAll('a')])
1597+ [link.find(text=True) for link in table.find_all('a')])
1598
1599 def test_copes_with_private_repos(self):
1600 invisible_repo = self.factory.makeGitRepository(
1601@@ -234,7 +234,7 @@ class TestPersonTargetGitListingView:
1602 'div', id='default-repository-branches').find('table')
1603 self.assertContentEqual(
1604 ['master', 'bug-1234'],
1605- [link.find(text=True) for link in table.findAll('a')])
1606+ [link.find(text=True) for link in table.find_all('a')])
1607 self.assertEndsWith(
1608 table.find(text="bug-1234").parent['href'],
1609 "/~dev/%s/+git/foo/+ref/bug-1234" % self.target_path)
1610@@ -245,7 +245,7 @@ class TestPersonTargetGitListingView:
1611 self.assertContentEqual(
1612 ['lp:~dev/%s' % self.target_path,
1613 'lp:~dev/%s/+git/bar' % self.target_path],
1614- [link.find(text=True) for link in table.findAll('a')])
1615+ [link.find(text=True) for link in table.find_all('a')])
1616 self.assertEndsWith(
1617 table.find(
1618 text="lp:~dev/%s/+git/bar" % self.target_path).parent['href'],
1619@@ -275,7 +275,7 @@ class TestPersonTargetGitListingView:
1620 'div', id='gitrepositories-table-listing').find('table')
1621 self.assertContentEqual(
1622 ['lp:~dev/%s/+git/foo' % self.target_path],
1623- [link.find(text=True) for link in table.findAll('a')])
1624+ [link.find(text=True) for link in table.find_all('a')])
1625
1626 def test_copes_with_private_repos(self):
1627 invisible_repo = self.factory.makeGitRepository(
1628@@ -492,7 +492,7 @@ class TestPlainGitListingView:
1629 'div', id='gitrepositories-table-listing').find('table')
1630 self.assertContentEqual(
1631 [some_repo.git_identity, other_repo.git_identity],
1632- [link.find(text=True) for link in table.findAll('a')])
1633+ [link.find(text=True) for link in table.find_all('a')])
1634
1635 def test_copes_with_private_repos(self):
1636 # XXX wgrant 2015-06-12: owner is self.user instead of
1637diff --git a/lib/lp/code/browser/tests/test_gitref.py b/lib/lp/code/browser/tests/test_gitref.py
1638index 97ef0a3..d49b343 100644
1639--- a/lib/lp/code/browser/tests/test_gitref.py
1640+++ b/lib/lp/code/browser/tests/test_gitref.py
1641@@ -501,7 +501,7 @@ class TestGitRefView(BrowserTestCase):
1642 view = create_initialized_view(ref, "+index")
1643 contents = view()
1644 soup = BeautifulSoup(contents)
1645- details = soup.findAll(
1646+ details = soup.find_all(
1647 attrs={"class": re.compile(r"commit-details|commit-comment")})
1648 expected_texts = list(reversed([
1649 "%.7s...\nby\n%s\non 2015-01-%02d" % (
1650@@ -513,7 +513,7 @@ class TestGitRefView(BrowserTestCase):
1651 expected_texts, [extract_text(detail) for detail in details])
1652 self.assertEqual(
1653 [canonical_url(mp), canonical_url(mp.merge_source)],
1654- [link["href"] for link in details[5].findAll("a")])
1655+ [link["href"] for link in details[5].find_all("a")])
1656 self.assertThat(
1657 contents, Not(soupmatchers.HTMLContains(MissingCommitsNote())))
1658
1659@@ -532,7 +532,7 @@ class TestGitRefView(BrowserTestCase):
1660 view = create_initialized_view(ref, "+index")
1661 contents = view()
1662 soup = BeautifulSoup(contents)
1663- details = soup.findAll(
1664+ details = soup.find_all(
1665 attrs={"class": re.compile(r"commit-details|commit-comment")})
1666 expected_texts = list(reversed([
1667 "%.7s...\nby\n%s\non 2015-01-%02d" % (
1668@@ -544,7 +544,7 @@ class TestGitRefView(BrowserTestCase):
1669 expected_texts, [extract_text(detail) for detail in details])
1670 self.assertEqual(
1671 [canonical_url(mp)],
1672- [link["href"] for link in details[5].findAll("a")])
1673+ [link["href"] for link in details[5].find_all("a")])
1674 self.assertThat(
1675 contents, Not(soupmatchers.HTMLContains(MissingCommitsNote())))
1676
1677@@ -629,7 +629,7 @@ class TestGitRefView(BrowserTestCase):
1678 view = create_initialized_view(ref, "+index")
1679 contents = view()
1680 soup = BeautifulSoup(contents)
1681- details = soup.findAll(
1682+ details = soup.find_all(
1683 attrs={"class": re.compile(r"commit-details|commit-comment")})
1684 expected_text = "%.7s...\nby\n%s\non 2015-01-%02d" % (
1685 log[-1]["sha1"], log[-1]["author"]["name"], len(log))
1686diff --git a/lib/lp/code/browser/tests/test_gitrepository.py b/lib/lp/code/browser/tests/test_gitrepository.py
1687index 8dadb9d..843d60a 100644
1688--- a/lib/lp/code/browser/tests/test_gitrepository.py
1689+++ b/lib/lp/code/browser/tests/test_gitrepository.py
1690@@ -1717,7 +1717,7 @@ class TestGitRepositoryPermissionsView(BrowserTestCase):
1691 repository, name="+permissions", principal=repository.owner)
1692 rules_tables = find_tags_by_class(view(), "git-rules-table")
1693 rows = list(chain.from_iterable([
1694- rules_table.findAll("tr", {"class": True})
1695+ rules_table.find_all("tr", {"class": True})
1696 for rules_table in rules_tables]))
1697 self.assertThat(rows, MatchesListwise([
1698 self._matchesRule("1", "refs/heads/stable/*", "stable/*"),
1699diff --git a/lib/lp/code/browser/tests/test_gitsubscription.py b/lib/lp/code/browser/tests/test_gitsubscription.py
1700index a887c38..17c9136 100644
1701--- a/lib/lp/code/browser/tests/test_gitsubscription.py
1702+++ b/lib/lp/code/browser/tests/test_gitsubscription.py
1703@@ -86,7 +86,7 @@ class TestGitSubscriptionAddView(BrowserTestCase):
1704 def _getSubscribers(self, contents):
1705 subscriptions = find_tags_by_class(
1706 contents, 'repository-subscribers')[0]
1707- for subscriber in subscriptions.findAll('div'):
1708+ for subscriber in subscriptions.find_all('div'):
1709 yield extract_text(subscriber.decode_contents())
1710
1711 def _getInformationalMessage(self, contents):
1712diff --git a/lib/lp/code/browser/tests/test_sourcepackagerecipe.py b/lib/lp/code/browser/tests/test_sourcepackagerecipe.py
1713index 94de042..5ab4908 100644
1714--- a/lib/lp/code/browser/tests/test_sourcepackagerecipe.py
1715+++ b/lib/lp/code/browser/tests/test_sourcepackagerecipe.py
1716@@ -132,11 +132,11 @@ class BzrMixin:
1717 if not related_package_branch_info:
1718 self.assertIs(branch_table, None)
1719 else:
1720- rows = branch_table.tbody.findAll('tr')
1721+ rows = branch_table.tbody.find_all('tr')
1722
1723 package_branches_info = []
1724 for row in rows:
1725- branch_links = row.findAll('a')
1726+ branch_links = row.find_all('a')
1727 self.assertEqual(2, len(branch_links))
1728 package_branches_info.append(
1729 '%s%s' % (root_url, branch_links[0]['href']))
1730@@ -162,11 +162,11 @@ class BzrMixin:
1731 if not related_series_branch_info:
1732 self.assertIs(branch_table, None)
1733 else:
1734- rows = branch_table.tbody.findAll('tr')
1735+ rows = branch_table.tbody.find_all('tr')
1736
1737 series_branches_info = []
1738 for row in rows:
1739- branch_links = row.findAll('a')
1740+ branch_links = row.find_all('a')
1741 self.assertEqual(2, len(branch_links))
1742 series_branches_info.append(
1743 '%s%s' % (root_url, branch_links[0]['href']))
1744diff --git a/lib/lp/code/browser/widgets/tests/test_branchtargetwidget.py b/lib/lp/code/browser/widgets/tests/test_branchtargetwidget.py
1745index 7b78126..e9f871b 100644
1746--- a/lib/lp/code/browser/widgets/tests/test_branchtargetwidget.py
1747+++ b/lib/lp/code/browser/widgets/tests/test_branchtargetwidget.py
1748@@ -244,6 +244,6 @@ class LaunchpadTargetWidgetTestCase(TestCaseWithFactory):
1749 'field.target.product',
1750 ]
1751 soup = BeautifulSoup(markup)
1752- fields = soup.findAll(['input', 'select'], {'id': re.compile('.*')})
1753+ fields = soup.find_all(['input', 'select'], {'id': re.compile('.*')})
1754 ids = [field['id'] for field in fields]
1755 self.assertContentEqual(expected_ids, ids)
1756diff --git a/lib/lp/code/browser/widgets/tests/test_gitgrantee.py b/lib/lp/code/browser/widgets/tests/test_gitgrantee.py
1757index 9d30eef..28d0011 100644
1758--- a/lib/lp/code/browser/widgets/tests/test_gitgrantee.py
1759+++ b/lib/lp/code/browser/widgets/tests/test_gitgrantee.py
1760@@ -156,7 +156,7 @@ class TestGitGranteeWidgetBase:
1761 self.assertIn("repository_owner", self.widget.options)
1762 self.assertIn("person", self.widget.options)
1763 soup = BeautifulSoup(markup)
1764- fields = soup.findAll(["input", "select"], {"id": re.compile(".*")})
1765+ fields = soup.find_all(["input", "select"], {"id": re.compile(".*")})
1766 ids = [field["id"] for field in fields]
1767 self.assertContentEqual(self.expected_ids, ids)
1768
1769diff --git a/lib/lp/code/browser/widgets/tests/test_gitrefwidget.py b/lib/lp/code/browser/widgets/tests/test_gitrefwidget.py
1770index 9b8e76c..cf61a8f 100644
1771--- a/lib/lp/code/browser/widgets/tests/test_gitrefwidget.py
1772+++ b/lib/lp/code/browser/widgets/tests/test_gitrefwidget.py
1773@@ -306,7 +306,7 @@ class TestGitRefWidget(WithScenarios, TestCaseWithFactory):
1774 self.assertIsNotNone(self.widget.repository_widget)
1775 self.assertIsNotNone(self.widget.path_widget)
1776 soup = BeautifulSoup(markup)
1777- fields = soup.findAll("input", id=True)
1778+ fields = soup.find_all("input", id=True)
1779 ids = [field["id"] for field in fields]
1780 self.assertContentEqual(
1781 ["field.git_ref.repository", "field.git_ref.path"], ids)
1782diff --git a/lib/lp/code/browser/widgets/tests/test_gitrepositorytargetwidget.py b/lib/lp/code/browser/widgets/tests/test_gitrepositorytargetwidget.py
1783index ebe6e9a..3d1c5b7 100644
1784--- a/lib/lp/code/browser/widgets/tests/test_gitrepositorytargetwidget.py
1785+++ b/lib/lp/code/browser/widgets/tests/test_gitrepositorytargetwidget.py
1786@@ -253,7 +253,7 @@ class TestGitRepositoryTargetWidgetBase:
1787 self.assertIn("personal", self.widget.options)
1788 self.assertIn("package", self.widget.options)
1789 soup = BeautifulSoup(markup)
1790- fields = soup.findAll(["input", "select"], {"id": re.compile(".*")})
1791+ fields = soup.find_all(["input", "select"], {"id": re.compile(".*")})
1792 ids = [field["id"] for field in fields]
1793 self.assertContentEqual(self.expected_ids, ids)
1794
1795diff --git a/lib/lp/code/stories/branches/xx-bazaar-home.txt b/lib/lp/code/stories/branches/xx-bazaar-home.txt
1796index f2a5868..df4a3df 100644
1797--- a/lib/lp/code/stories/branches/xx-bazaar-home.txt
1798+++ b/lib/lp/code/stories/branches/xx-bazaar-home.txt
1799@@ -34,7 +34,7 @@ with a link to the complete listing.
1800 Most active projects in the last month
1801 see all projects…
1802
1803- >>> print(preview.findAll('a')[-1]['href'])
1804+ >>> print(preview.find_all('a')[-1]['href'])
1805 /projects
1806
1807
1808@@ -72,7 +72,7 @@ The recently registered branch listing is ordered with the most recently
1809 registered branches first.
1810
1811 >>> registered = find_tag_by_id(browser.contents, 'recently-registered')
1812- >>> print(registered.findAll('a')[-1]['href'])
1813+ >>> print(registered.find_all('a')[-1]['href'])
1814 /+recently-registered-branches
1815
1816 >>> browser.getLink(url='recently-registered-branches').click()
1817@@ -84,7 +84,7 @@ is also shown in the listing. And since the date that the branch was
1818 registered is the ordering, the registered date is also shown.
1819
1820 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1821- >>> for row in table.thead.findAll('tr'):
1822+ >>> for row in table.thead.find_all('tr'):
1823 ... print(extract_text(row))
1824 Name
1825 Status
1826@@ -105,7 +105,7 @@ recent commits first.
1827
1828 >>> browser.open('http://code.launchpad.test/')
1829 >>> changed = find_tag_by_id(browser.contents, 'recently-changed')
1830- >>> print(changed.findAll('a')[-1]['href'])
1831+ >>> print(changed.find_all('a')[-1]['href'])
1832 /+recently-changed-branches
1833
1834 >>> browser.getLink(url='recently-changed-branches').click()
1835@@ -113,7 +113,7 @@ recent commits first.
1836 Recently changed branches
1837
1838 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1839- >>> for row in table.thead.findAll('tr'):
1840+ >>> for row in table.thead.find_all('tr'):
1841 ... print(extract_text(row))
1842 Name
1843 Status
1844@@ -132,7 +132,7 @@ imported branches.
1845
1846 >>> browser.open('http://code.launchpad.test/')
1847 >>> imported = find_tag_by_id(browser.contents, 'recent-imports')
1848- >>> print(imported.findAll('a')[-1]['href'])
1849+ >>> print(imported.find_all('a')[-1]['href'])
1850 /+recently-imported-branches
1851
1852 >>> browser.getLink(url='recently-imported-branches').click()
1853@@ -144,7 +144,7 @@ of the branches are not normally set, the Author column is not shown for
1854 imported branch listings.
1855
1856 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1857- >>> for row in table.thead.findAll('tr'):
1858+ >>> for row in table.thead.find_all('tr'):
1859 ... print(extract_text(row))
1860 Name
1861 Status
1862diff --git a/lib/lp/code/stories/branches/xx-branch-listings-merge-proposal-badge.txt b/lib/lp/code/stories/branches/xx-branch-listings-merge-proposal-badge.txt
1863index dee2a96..ce25e5c 100644
1864--- a/lib/lp/code/stories/branches/xx-branch-listings-merge-proposal-badge.txt
1865+++ b/lib/lp/code/stories/branches/xx-branch-listings-merge-proposal-badge.txt
1866@@ -2,13 +2,13 @@
1867
1868 >>> def branchSummary(browser):
1869 ... table = find_tag_by_id(browser.contents, 'branchtable')
1870- ... for row in table.tbody.findAll('tr'):
1871- ... cells = row.findAll('td')
1872+ ... for row in table.tbody.find_all('tr'):
1873+ ... cells = row.find_all('td')
1874 ... first_cell = cells[0]
1875- ... anchors = first_cell.findAll('a')
1876+ ... anchors = first_cell.find_all('a')
1877 ... print(anchors[0].get('href'))
1878 ... # Badges in the next cell
1879- ... for img in cells[1].findAll('img'):
1880+ ... for img in cells[1].find_all('img'):
1881 ... print(img['title'])
1882
1883
1884diff --git a/lib/lp/code/stories/branches/xx-branch-listings.txt b/lib/lp/code/stories/branches/xx-branch-listings.txt
1885index 463fc8d..b1e0399 100644
1886--- a/lib/lp/code/stories/branches/xx-branch-listings.txt
1887+++ b/lib/lp/code/stories/branches/xx-branch-listings.txt
1888@@ -28,7 +28,7 @@ branches in the listings.
1889 ...1...→...6...of 10 results...
1890
1891 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1892- >>> for row in table.thead.findAll('tr'):
1893+ >>> for row in table.thead.find_all('tr'):
1894 ... print(extract_text(row))
1895 Name
1896 Status
1897@@ -39,7 +39,7 @@ Unfortunately our sample data is somewhat lacking in the last commit
1898 fields. There are a couple of branches that have them, but most don't
1899 and are really just branch metadata without the revisions behind them.
1900
1901- >>> for row in table.tbody.findAll('tr'):
1902+ >>> for row in table.tbody.find_all('tr'):
1903 ... print(extract_text(row))
1904 lp://dev/~name12/firefox/main Development ...
1905 lp://dev/~name12/gnome-terminal/2.6 Mature ...
1906@@ -55,7 +55,7 @@ and are really just branch metadata without the revisions behind them.
1907 ...7...→...10...of 10 results...
1908
1909 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1910- >>> for row in table.tbody.findAll('tr'):
1911+ >>> for row in table.tbody.find_all('tr'):
1912 ... print(extract_text(row))
1913 lp://dev/~name12/gnome-terminal/klingon Experimental ...
1914 lp://dev/~name12/+junk/junk.contrib Development ...
1915@@ -82,7 +82,7 @@ shown.
1916
1917 >>> browser.open('http://code.launchpad.test/~name12')
1918 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1919- >>> for row in table.tbody.findAll('tr'):
1920+ >>> for row in table.tbody.find_all('tr'):
1921 ... print(extract_text(row))
1922 lp://dev/~name12/firefox/main Development ...
1923 lp://dev/~name12/gnome-terminal/2.6 Mature ...
1924@@ -117,7 +117,7 @@ Now all types of branches should be shown.
1925 ...1...→...6...of 12 results...
1926
1927 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1928- >>> for row in table.tbody.findAll('tr'):
1929+ >>> for row in table.tbody.find_all('tr'):
1930 ... print(extract_text(row))
1931 lp://dev/~name12/firefox/main Development ...
1932 lp://dev/~name12/gnome-terminal/2.4 Abandoned ...
1933@@ -133,7 +133,7 @@ Now all types of branches should be shown.
1934 ...7...→...12...of 12 results...
1935
1936 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1937- >>> for row in table.tbody.findAll('tr'):
1938+ >>> for row in table.tbody.find_all('tr'):
1939 ... print(extract_text(row))
1940 lp://dev/~name12/gnome-terminal/pushed Development ...
1941 lp://dev/~name12/gnome-terminal/scanned Development ...
1942@@ -148,7 +148,7 @@ will cause only branches with that status to be listed.
1943 >>> browser.getControl(name='field.lifecycle').displayValue = ['Abandoned']
1944 >>> browser.getControl('Filter').click()
1945 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1946- >>> for row in table.tbody.findAll('tr'):
1947+ >>> for row in table.tbody.find_all('tr'):
1948 ... print(extract_text(row))
1949 lp://dev/~name12/gnome-terminal/2.4 Abandoned ...
1950
1951@@ -160,7 +160,7 @@ status value, it will default to current branches.
1952 >>> browser.getControl(name='field.lifecycle').displayValue
1953 ['Any active status']
1954 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1955- >>> for row in table.tbody.findAll('tr'):
1956+ >>> for row in table.tbody.find_all('tr'):
1957 ... print(extract_text(row))
1958 lp://dev/~name12/firefox/main Development ...
1959 lp://dev/~name12/gnome-terminal/2.6 Mature ...
1960@@ -188,7 +188,7 @@ first.
1961 ... 'http://code.launchpad.test/~name12/+branches?'
1962 ... 'field.category=subscribed')
1963 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1964- >>> for row in table.tbody.findAll('tr'):
1965+ >>> for row in table.tbody.find_all('tr'):
1966 ... print(extract_text(row))
1967 lp://dev/~name12/firefox/main ...
1968 lp://dev/~launchpad/gnome-terminal/launchpad ...
1969@@ -212,17 +212,17 @@ We display badges for associated bugs.
1970
1971 >>> def branchSummary(browser):
1972 ... table = find_tag_by_id(browser.contents, 'branchtable')
1973- ... for row in table.tbody.findAll('tr'):
1974+ ... for row in table.tbody.find_all('tr'):
1975 ... if row.get_text(strip=True).startswith(
1976 ... 'A development focus branch'):
1977 ... continue
1978- ... cells = row.findAll('td')
1979+ ... cells = row.find_all('td')
1980 ... first_cell = cells[0]
1981- ... anchors = first_cell.findAll('a')
1982+ ... anchors = first_cell.find_all('a')
1983 ... print(anchors[0].get('href'))
1984 ... # Badges in the next cell
1985 ... if len(cells) > 1:
1986- ... for img in cells[1].findAll('img'):
1987+ ... for img in cells[1].find_all('img'):
1988 ... print(img['title'])
1989
1990 >>> browser.open(
1991@@ -337,7 +337,7 @@ Finally, sorting by a particular criterion has the desired effect.
1992
1993 >>> browser.open('http://code.launchpad.test/gnome-terminal/+branches')
1994 >>> table = find_tag_by_id(browser.contents, 'branchtable')
1995- >>> for row in table.tbody.findAll('tr'):
1996+ >>> for row in table.tbody.find_all('tr'):
1997 ... print(extract_text(row))
1998 A development focus ...
1999 lp://dev/~name12/gnome-terminal/2.6 Mature ...
2000@@ -350,7 +350,7 @@ Finally, sorting by a particular criterion has the desired effect.
2001 >>> browser.getControl(name='field.sort_by').value = ['by branch name']
2002 >>> browser.getControl('Filter').click()
2003 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2004- >>> for row in table.tbody.findAll('tr'):
2005+ >>> for row in table.tbody.find_all('tr'):
2006 ... print(extract_text(row))
2007 A development focus ...
2008 lp://dev/~name12/gnome-terminal/2.6 Mature ...
2009@@ -383,8 +383,8 @@ both the series link in the first column with the branch unique name.
2010 >>> browser.open('http://code.launchpad.test/gnome-terminal')
2011 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2012 >>> # The development focus is always first.
2013- >>> row = table.tbody.findAll('tr')[0]
2014- >>> cols = row.findAll('td')
2015+ >>> row = table.tbody.find_all('tr')[0]
2016+ >>> cols = row.find_all('td')
2017 >>> print(extract_text(cols[0]))
2018 lp://dev/gnome-terminal Series: trunk
2019
2020@@ -411,7 +411,7 @@ The current development focus is shown first though.
2021
2022 >>> browser.open('http://code.launchpad.test/gnome-terminal')
2023 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2024- >>> print(extract_text(table.tbody.findAll('tr')[0]))
2025+ >>> print(extract_text(table.tbody.find_all('tr')[0]))
2026 lp://dev/gnome-terminal Series: trunk, alpha, pre-1.0 ...
2027
2028
2029@@ -424,7 +424,7 @@ Merged or Abandoned branches are not shown.
2030
2031 >>> browser.open('http://code.launchpad.test/gnome-terminal')
2032 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2033- >>> for row in table.tbody.findAll('tr'):
2034+ >>> for row in table.tbody.find_all('tr'):
2035 ... print(extract_text(row))
2036 lp://dev/gnome-terminal Series: trunk... Development ...
2037 lp://dev/~name12/gnome-terminal/2.6 Mature ...
2038@@ -449,7 +449,7 @@ will cause only branches with that status to be listed.
2039 >>> browser.getControl(name='field.lifecycle').displayValue = ['Experimental']
2040 >>> browser.getControl('Filter').click()
2041 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2042- >>> for row in table.tbody.findAll('tr'):
2043+ >>> for row in table.tbody.find_all('tr'):
2044 ... print(extract_text(row))
2045 lp://dev/~name12/gnome-terminal/klingon Experimental ...
2046
2047@@ -459,7 +459,7 @@ first.
2048 >>> browser.getControl(name='field.lifecycle').displayValue = ['Development']
2049 >>> browser.getControl('Filter').click()
2050 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2051- >>> for row in table.tbody.findAll('tr'):
2052+ >>> for row in table.tbody.find_all('tr'):
2053 ... print(extract_text(row))
2054 lp://dev/gnome-terminal Series: trunk... Development ...
2055
2056diff --git a/lib/lp/code/stories/branches/xx-branch-tag-cloud.txt b/lib/lp/code/stories/branches/xx-branch-tag-cloud.txt
2057index aed92a3..7e00f56 100644
2058--- a/lib/lp/code/stories/branches/xx-branch-tag-cloud.txt
2059+++ b/lib/lp/code/stories/branches/xx-branch-tag-cloud.txt
2060@@ -24,7 +24,7 @@ branches associated with it. The HTML class attribute is used to control how
2061 the link is shown.
2062
2063 >>> tags = find_tag_by_id(anon_browser.contents, 'project-tags')
2064- >>> for anchor in tags.findAll('a'):
2065+ >>> for anchor in tags.find_all('a'):
2066 ... print(anchor.decode_contents(), ' '.join(anchor['class']))
2067 linux cloud-size-largest cloud-medium
2068 wibble cloud-size-smallest cloud-dark
2069diff --git a/lib/lp/code/stories/branches/xx-branchmergeproposals.txt b/lib/lp/code/stories/branches/xx-branchmergeproposals.txt
2070index 6c8a697..798c6d0 100644
2071--- a/lib/lp/code/stories/branches/xx-branchmergeproposals.txt
2072+++ b/lib/lp/code/stories/branches/xx-branchmergeproposals.txt
2073@@ -376,7 +376,7 @@ branch widget is shown.
2074 >>> import re
2075 >>> def get_target_branch_widgets(browser):
2076 ... main = find_main_content(browser.contents)
2077- ... return main.findAll(
2078+ ... return main.find_all(
2079 ... 'input', attrs={'name': re.compile('target_branch')})
2080
2081 >>> nopriv_browser.open(
2082diff --git a/lib/lp/code/stories/branches/xx-code-review-comments.txt b/lib/lp/code/stories/branches/xx-code-review-comments.txt
2083index 485805b..1c3738d 100644
2084--- a/lib/lp/code/stories/branches/xx-code-review-comments.txt
2085+++ b/lib/lp/code/stories/branches/xx-code-review-comments.txt
2086@@ -115,7 +115,7 @@ are also displayed in the new proposal.
2087 Posted in a previous version of this proposal #
2088 >>> details = find_tags_by_class(
2089 ... anon_browser.contents, 'boardCommentDetails')[0]
2090- >>> links = details.findAll('a')
2091+ >>> links = details.find_all('a')
2092 >>> print(links[1]['href'] == merge_proposal_path)
2093 True
2094
2095@@ -270,7 +270,7 @@ rendered with the following 'data-' attributes:
2096 ... result = {}
2097 ... comments = find_tags_by_class(contents, 'boardCommentDetails')
2098 ... for comment in comments:
2099- ... tds = comment.findAll('td')
2100+ ... tds = comment.find_all('td')
2101 ... if len(tds) == 0:
2102 ... continue
2103 ... td = tds[0]
2104diff --git a/lib/lp/code/stories/branches/xx-nearby-branches.txt b/lib/lp/code/stories/branches/xx-nearby-branches.txt
2105index 3b10d7c..16927b3 100644
2106--- a/lib/lp/code/stories/branches/xx-nearby-branches.txt
2107+++ b/lib/lp/code/stories/branches/xx-nearby-branches.txt
2108@@ -18,7 +18,7 @@ branches.
2109 Since the links point to the code subdomain, the links are relative to the root.
2110
2111 >>> div = find_tag_by_id(browser.contents, 'nearby-branches')
2112- >>> for anchor in div.findAll('a'):
2113+ >>> for anchor in div.find_all('a'):
2114 ... print(anchor['href'], anchor.string)
2115 /fooix Other Fooix branches
2116 /~vikings Other branches owned by Vikings
2117diff --git a/lib/lp/code/stories/branches/xx-person-branches.txt b/lib/lp/code/stories/branches/xx-person-branches.txt
2118index 054c2af..ac50523 100644
2119--- a/lib/lp/code/stories/branches/xx-person-branches.txt
2120+++ b/lib/lp/code/stories/branches/xx-person-branches.txt
2121@@ -46,7 +46,7 @@ A person's owned branches are shown on their code application overview page.
2122
2123 >>> browser.open('http://code.launchpad.test/~name12')
2124 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2125- >>> for row in table.tbody.findAll('tr'):
2126+ >>> for row in table.tbody.find_all('tr'):
2127 ... print(extract_text(row))
2128 lp://dev/~name12/landscape/feature-x Development
2129 ...
2130@@ -64,7 +64,7 @@ There is also a filter for registered branches.
2131 >>> print(browser.title)
2132 Code : Sample Person
2133 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2134- >>> for row in table.tbody.findAll('tr'):
2135+ >>> for row in table.tbody.find_all('tr'):
2136 ... print(extract_text(row))
2137 lp://dev/~name12/landscape/feature-x Development
2138 ...
2139@@ -83,7 +83,7 @@ subscribed branches.
2140 >>> print(browser.title)
2141 Code : Sample Person
2142 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2143- >>> for row in table.tbody.findAll('tr'):
2144+ >>> for row in table.tbody.find_all('tr'):
2145 ... print(extract_text(row))
2146 lp://dev/~launchpad/gnome-terminal/launchpad Development ...
2147 lp://dev/~name12/+junk/junk.dev Experimental ...
2148diff --git a/lib/lp/code/stories/branches/xx-private-branch-listings.txt b/lib/lp/code/stories/branches/xx-private-branch-listings.txt
2149index 4fa90cc..a1fbbe3 100644
2150--- a/lib/lp/code/stories/branches/xx-private-branch-listings.txt
2151+++ b/lib/lp/code/stories/branches/xx-private-branch-listings.txt
2152@@ -49,7 +49,7 @@ registered branches.
2153 >>> def print_recently_registered_branches(browser):
2154 ... browser.open('http://code.launchpad.test')
2155 ... branches = find_tag_by_id(browser.contents, 'recently-registered')
2156- ... for list_item in branches.ul.findAll('li'):
2157+ ... for list_item in branches.ul.find_all('li'):
2158 ... print("%r" % list_item.decode_contents())
2159
2160 When there is no logged in user, only public branches should be visible.
2161@@ -117,7 +117,7 @@ listing tab.
2162 ... print(extract_text(find_tag_by_id(
2163 ... browser.contents, 'branch-summary')))
2164 ... else:
2165- ... for row in table.tbody.findAll('tr'):
2166+ ... for row in table.tbody.find_all('tr'):
2167 ... print(extract_text(row))
2168
2169 >>> print_landscape_code_listing(anon_browser)
2170@@ -157,7 +157,7 @@ viewable branches.
2171 ... browser.open(full_url)
2172 ... table = find_tag_by_id(browser.contents, 'branchtable')
2173 ... branches = []
2174- ... for row in table.tbody.findAll('tr'):
2175+ ... for row in table.tbody.find_all('tr'):
2176 ... branches.append(extract_text(row))
2177 ... landscape_branches = [branch for branch in branches
2178 ... if 'landscape' in branch]
2179diff --git a/lib/lp/code/stories/branches/xx-product-branches.txt b/lib/lp/code/stories/branches/xx-product-branches.txt
2180index a9af801..9ca90d2 100644
2181--- a/lib/lp/code/stories/branches/xx-product-branches.txt
2182+++ b/lib/lp/code/stories/branches/xx-product-branches.txt
2183@@ -54,7 +54,7 @@ If there are not any branches, a helpful message is shown.
2184
2185 The 'Help' links go to the help wiki.
2186
2187- >>> for anchor in summary.findAll('a'):
2188+ >>> for anchor in summary.find_all('a'):
2189 ... print(anchor['href'])
2190 https://help.launchpad.net/Code
2191
2192@@ -97,7 +97,7 @@ shown.
2193 using the command:
2194 bzr branch lp://dev/evolution
2195
2196- >>> links = summary.findAll('a')
2197+ >>> links = summary.find_all('a')
2198
2199 Both active reviews and approved merges are links allowing the user to
2200 go to listing views.
2201@@ -123,7 +123,7 @@ once, but both series are shown in the listing.
2202
2203 >>> browser.open('http://code.launchpad.test/firefox')
2204 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2205- >>> for row in table.tbody.findAll('tr')[0:2]:
2206+ >>> for row in table.tbody.find_all('tr')[0:2]:
2207 ... print(extract_text(row))
2208 lp://dev/firefox
2209 Series: trunk, 1.0 Development ...
2210@@ -138,7 +138,7 @@ Firstly lets associate release--0.9.1 with the 1.0 series.
2211
2212 >>> browser.open('http://code.launchpad.test/firefox')
2213 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2214- >>> for row in table.tbody.findAll('tr')[0:2]:
2215+ >>> for row in table.tbody.find_all('tr')[0:2]:
2216 ... print(extract_text(row))
2217 lp://dev/firefox
2218 Series: trunk Development ...
2219@@ -159,7 +159,7 @@ default listings.
2220
2221 >>> browser.open('http://code.launchpad.test/firefox')
2222 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2223- >>> for row in table.tbody.findAll('tr')[0:2]:
2224+ >>> for row in table.tbody.find_all('tr')[0:2]:
2225 ... print(extract_text(row))
2226 lp://dev/~mark/firefox/release-0.8 Development ...
2227
2228@@ -187,7 +187,7 @@ The links are only shown if the user has permission to perform the task.
2229 ... if links is None:
2230 ... print('None')
2231 ... return
2232- ... for link in links.findAll('a'):
2233+ ... for link in links.find_all('a'):
2234 ... print(extract_text(link))
2235
2236 >>> def setup_code_hosting(productname):
2237diff --git a/lib/lp/code/stories/branches/xx-product-overview.txt b/lib/lp/code/stories/branches/xx-product-overview.txt
2238index 5c0255c..7f9b8dd 100644
2239--- a/lib/lp/code/stories/branches/xx-product-overview.txt
2240+++ b/lib/lp/code/stories/branches/xx-product-overview.txt
2241@@ -10,7 +10,7 @@ registered branches.
2242 ... if branches is None:
2243 ... print("No 'Latest branches' portlet found at %s" % (url,))
2244 ... return
2245- ... for list_item in branches.findAll('li'):
2246+ ... for list_item in branches.find_all('li'):
2247 ... print(extract_text(list_item))
2248
2249 >>> def make_branch_on_product(product, branch_name, person_name):
2250diff --git a/lib/lp/code/stories/branches/xx-project-branches.txt b/lib/lp/code/stories/branches/xx-project-branches.txt
2251index 941ab3d..baad3b3 100644
2252--- a/lib/lp/code/stories/branches/xx-project-branches.txt
2253+++ b/lib/lp/code/stories/branches/xx-project-branches.txt
2254@@ -24,7 +24,7 @@ If there are branches, then they are displayed.
2255
2256 >>> browser.open('http://code.launchpad.test/mozilla')
2257 >>> table = find_tag_by_id(browser.contents, 'branchtable')
2258- >>> for row in table.tbody.findAll('tr'):
2259+ >>> for row in table.tbody.find_all('tr'):
2260 ... print(extract_text(row))
2261 lp://dev/~mark/firefox/release--0.9.1 Development firefox ...
2262 lp://dev/~mark/firefox/release-0.8 Development firefox ...
2263diff --git a/lib/lp/code/stories/branches/xx-propose-for-merging.txt b/lib/lp/code/stories/branches/xx-propose-for-merging.txt
2264index fb0cb89..c2fdf36 100644
2265--- a/lib/lp/code/stories/branches/xx-propose-for-merging.txt
2266+++ b/lib/lp/code/stories/branches/xx-propose-for-merging.txt
2267@@ -25,7 +25,7 @@ branch.
2268
2269 >>> def print_radio_buttons(browser):
2270 ... main = find_main_content(browser.contents)
2271- ... for button in main.findAll('input', attrs={'type': 'radio'}):
2272+ ... for button in main.find_all('input', attrs={'type': 'radio'}):
2273 ... try:
2274 ... if button['checked']:
2275 ... checked = '(*)'
2276diff --git a/lib/lp/code/stories/branches/xx-source-package-branches-listing.txt b/lib/lp/code/stories/branches/xx-source-package-branches-listing.txt
2277index 4aab30a..7f8a8f7 100644
2278--- a/lib/lp/code/stories/branches/xx-source-package-branches-listing.txt
2279+++ b/lib/lp/code/stories/branches/xx-source-package-branches-listing.txt
2280@@ -34,7 +34,7 @@ Both of the branches we made appear in the listing.
2281
2282 >>> def print_branches(browser):
2283 ... table = find_tag_by_id(browser.contents, 'branchtable')
2284- ... for row in table.tbody.findAll('tr'):
2285+ ... for row in table.tbody.find_all('tr'):
2286 ... print(extract_text(row))
2287 >>> print_branches(browser)
2288 lp://dev/~owner1/distro/series/foo/branch1 ...
2289diff --git a/lib/lp/code/stories/branches/xx-subscribing-branches.txt b/lib/lp/code/stories/branches/xx-subscribing-branches.txt
2290index de24148..f240f47 100644
2291--- a/lib/lp/code/stories/branches/xx-subscribing-branches.txt
2292+++ b/lib/lp/code/stories/branches/xx-subscribing-branches.txt
2293@@ -9,7 +9,7 @@ A quick helper function to list the subscribed people.
2294 ... if subscriptions == None:
2295 ... print(subscriptions)
2296 ... return
2297- ... for subscriber in subscriptions.findAll('div'):
2298+ ... for subscriber in subscriptions.find_all('div'):
2299 ... print(extract_text(subscriber.decode_contents()))
2300
2301 Another to print the informational message.
2302diff --git a/lib/lp/code/stories/codeimport/xx-codeimport-results.txt b/lib/lp/code/stories/codeimport/xx-codeimport-results.txt
2303index 039ee60..e78f26c 100644
2304--- a/lib/lp/code/stories/codeimport/xx-codeimport-results.txt
2305+++ b/lib/lp/code/stories/codeimport/xx-codeimport-results.txt
2306@@ -53,7 +53,7 @@ is the text of the failure or success type.
2307
2308 >>> # The ordering here is dependant on the order the status values
2309 >>> # are declared in the enumeration.
2310- >>> for img in import_results.findAll('img'):
2311+ >>> for img in import_results.find_all('img'):
2312 ... print(img)
2313 <img src="/@@/no" title="Unsupported feature"/>
2314 <img src="/@@/no" title="Foreign branch invalid"/>
2315@@ -65,7 +65,7 @@ is the text of the failure or success type.
2316
2317 >>> browser.open(branch_url_2)
2318 >>> import_results = find_tag_by_id(browser.contents, 'import-results')
2319- >>> for img in import_results.findAll('img'):
2320+ >>> for img in import_results.find_all('img'):
2321 ... print(img)
2322 <img src="/@@/no" title="Job killed"/>
2323 <img src="/@@/no" title="Job reclaimed"/>
2324diff --git a/lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt b/lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt
2325index 688e713..a1876cd 100644
2326--- a/lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt
2327+++ b/lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt
2328@@ -7,12 +7,12 @@ page template, and views derived from RecipeListingView.
2329
2330 >>> def print_recipe_listing_head(browser):
2331 ... table = find_tag_by_id(browser.contents, 'recipetable')
2332- ... for row in table.thead.findAll('tr'):
2333+ ... for row in table.thead.find_all('tr'):
2334 ... print(extract_text(row))
2335
2336 >>> def print_recipe_listing_contents(browser):
2337 ... table = find_tag_by_id(browser.contents, 'recipetable')
2338- ... for row in table.tbody.findAll('tr'):
2339+ ... for row in table.tbody.find_all('tr'):
2340 ... print(extract_text(row))
2341
2342
2343diff --git a/lib/lp/coop/answersbugs/stories/question-makebug.txt b/lib/lp/coop/answersbugs/stories/question-makebug.txt
2344index e47b617..029f8cb 100644
2345--- a/lib/lp/coop/answersbugs/stories/question-makebug.txt
2346+++ b/lib/lp/coop/answersbugs/stories/question-makebug.txt
2347@@ -53,7 +53,7 @@ The bug page will display a link to the originating question in the 'Related
2348 questions' portlet:
2349
2350 >>> portlet = find_portlet(browser.contents, 'Related questions')
2351- >>> for question in portlet.findAll('li', 'question-row'):
2352+ >>> for question in portlet.find_all('li', 'question-row'):
2353 ... print(question.decode_contents())
2354 <span class="sprite question">Mozilla Firefox</span>: ...<a href=".../firefox/+question/2">Problem...
2355
2356diff --git a/lib/lp/registry/browser/tests/coc-views.txt b/lib/lp/registry/browser/tests/coc-views.txt
2357index ced69df..f8a21d5 100644
2358--- a/lib/lp/registry/browser/tests/coc-views.txt
2359+++ b/lib/lp/registry/browser/tests/coc-views.txt
2360@@ -24,7 +24,7 @@ key registered, directions are shown.
2361 >>> def print_coc_directions(content):
2362 ... ol = content.find('ol')
2363 ... if ol is not None:
2364- ... for index, li in enumerate(ol.findAll('li')):
2365+ ... for index, li in enumerate(ol.find_all('li')):
2366 ... print('%s. %s' % ((index+1), extract_text(li)))
2367 >>> user = factory.makePerson()
2368 >>> ignored = login_person(user)
2369diff --git a/lib/lp/registry/browser/tests/packaging-views.txt b/lib/lp/registry/browser/tests/packaging-views.txt
2370index 98dd27d..42e26a5 100644
2371--- a/lib/lp/registry/browser/tests/packaging-views.txt
2372+++ b/lib/lp/registry/browser/tests/packaging-views.txt
2373@@ -273,7 +273,7 @@ instead.)
2374
2375 # There are links to the +remove-packaging page.
2376 >>> table = find_tag_by_id(view.render(), 'packages-hotter')
2377- >>> for link in table.findAll('a'):
2378+ >>> for link in table.find_all('a'):
2379 ... if '+remove-packaging' in link['href']:
2380 ... print(link['href'])
2381 http://launchpad.test/ubuntu/grumpy/+source/hot/+remove-packaging
2382diff --git a/lib/lp/registry/browser/tests/sourcepackage-views.txt b/lib/lp/registry/browser/tests/sourcepackage-views.txt
2383index b7f4140..e15111c 100644
2384--- a/lib/lp/registry/browser/tests/sourcepackage-views.txt
2385+++ b/lib/lp/registry/browser/tests/sourcepackage-views.txt
2386@@ -172,7 +172,7 @@ bonkers project, the portlet will display that information.
2387 >>> from lp.testing.pages import (
2388 ... extract_text, find_tag_by_id)
2389 >>> content = find_tag_by_id(view.render(), 'upstreams')
2390- >>> for link in content.findAll('a'):
2391+ >>> for link in content.find_all('a'):
2392 ... print(link['href'])
2393 /bonkers
2394 /bonkers/crazy
2395diff --git a/lib/lp/registry/browser/tests/test_distroseries.py b/lib/lp/registry/browser/tests/test_distroseries.py
2396index 063158d..46ab789 100644
2397--- a/lib/lp/registry/browser/tests/test_distroseries.py
2398+++ b/lib/lp/registry/browser/tests/test_distroseries.py
2399@@ -1183,7 +1183,7 @@ class TestDistroSeriesLocalDifferences(TestCaseWithFactory,
2400 view = self.makeView(derived_series)
2401
2402 soup = BeautifulSoup(view())
2403- help_links = soup.findAll(
2404+ help_links = soup.find_all(
2405 'a', href='/+help-soyuz/derived-series-syncing.html')
2406 self.assertEqual(1, len(help_links))
2407
2408@@ -1202,7 +1202,7 @@ class TestDistroSeriesLocalDifferences(TestCaseWithFactory,
2409 # listing the differences.
2410 soup = BeautifulSoup(view())
2411 diff_table = soup.find('table', {'class': 'listing'})
2412- rows = diff_table.tbody.findAll('tr')
2413+ rows = diff_table.tbody.find_all('tr')
2414
2415 self.assertEqual(1, len(rows))
2416 self.assertIn("Latest comment", six.text_type(rows[0]))
2417@@ -1217,9 +1217,9 @@ class TestDistroSeriesLocalDifferences(TestCaseWithFactory,
2418 view = self.makeView(derived_series)
2419 soup = BeautifulSoup(view())
2420 diff_table = soup.find('table', {'class': 'listing'})
2421- row = diff_table.tbody.findAll('tr')[0]
2422+ row = diff_table.tbody.find_all('tr')[0]
2423
2424- links = row.findAll('a', href=canonical_url(difference))
2425+ links = row.find_all('a', href=canonical_url(difference))
2426 self.assertEqual(1, len(links))
2427 self.assertEqual(difference.source_package_name.name, links[0].string)
2428
2429@@ -1289,7 +1289,7 @@ class TestDistroSeriesLocalDifferences(TestCaseWithFactory,
2430 soup = BeautifulSoup(view())
2431 diff_table = soup.find('table', {'class': 'listing'})
2432 row = diff_table.tbody.tr
2433- links = row.findAll('a', {'class': 'derived-version'})
2434+ links = row.find_all('a', {'class': 'derived-version'})
2435
2436 # The version displayed is the version attached to the
2437 # difference.
2438@@ -1334,8 +1334,8 @@ class TestDistroSeriesLocalDifferences(TestCaseWithFactory,
2439
2440 # The table feature a simple span since we were unable to fetch a
2441 # published sourcepackage.
2442- derived_span = row.findAll('span', {'class': 'derived-version'})
2443- parent_span = row.findAll('span', {'class': 'parent-version'})
2444+ derived_span = row.find_all('span', {'class': 'derived-version'})
2445+ parent_span = row.find_all('span', {'class': 'parent-version'})
2446 self.assertEqual(1, len(derived_span))
2447 self.assertEqual(1, len(parent_span))
2448
2449@@ -1387,7 +1387,7 @@ class TestDistroSeriesLocalDifferences(TestCaseWithFactory,
2450 diff_table = soup.find('table', {'class': 'listing'})
2451 row = diff_table.tbody.tr
2452
2453- changelog_span = row.findAll('span', {'class': 'lesser'})
2454+ changelog_span = row.find_all('span', {'class': 'lesser'})
2455 self.assertEqual(1, len(changelog_span))
2456 link = changelog_span[0].a
2457 self.assertEqual("changelog", link.string)
2458diff --git a/lib/lp/registry/browser/tests/test_distroseriesdifference_views.py b/lib/lp/registry/browser/tests/test_distroseriesdifference_views.py
2459index 6f138a5..4de09b6 100644
2460--- a/lib/lp/registry/browser/tests/test_distroseriesdifference_views.py
2461+++ b/lib/lp/registry/browser/tests/test_distroseriesdifference_views.py
2462@@ -239,7 +239,7 @@ class DistroSeriesDifferenceTestCase(TestCaseWithFactory):
2463 view = create_initialized_view(
2464 ds_diff, '+listing-distroseries-extra')
2465 soup = BeautifulSoup(view())
2466- tags = soup.find('ul', 'package-diff-status').findAll('span')
2467+ tags = soup.find('ul', 'package-diff-status').find_all('span')
2468 self.assertEqual(2, len(tags))
2469
2470 def test_do_not_display_child_diff(self):
2471@@ -261,7 +261,7 @@ class DistroSeriesDifferenceTestCase(TestCaseWithFactory):
2472 view = create_initialized_view(
2473 ds_diff, '+listing-distroseries-extra')
2474 soup = BeautifulSoup(view())
2475- tags = soup.find('ul', 'package-diff-status').findAll('span')
2476+ tags = soup.find('ul', 'package-diff-status').find_all('span')
2477 self.assertEqual(1, len(tags))
2478
2479 def test_do_not_display_parent_diff(self):
2480@@ -283,7 +283,7 @@ class DistroSeriesDifferenceTestCase(TestCaseWithFactory):
2481 view = create_initialized_view(
2482 ds_diff, '+listing-distroseries-extra')
2483 soup = BeautifulSoup(view())
2484- tags = soup.find('ul', 'package-diff-status').findAll('span')
2485+ tags = soup.find('ul', 'package-diff-status').find_all('span')
2486 self.assertEqual(1, len(tags))
2487
2488 def _assertNoRequestLink(self, ds_diff):
2489@@ -372,7 +372,7 @@ class DistroSeriesDifferenceTemplateTestCase(TestCaseWithFactory):
2490 else:
2491 soup = html_or_soup
2492 class_dict = {'class': re.compile('request-derived-diff')}
2493- return len(soup.findAll('span', class_dict))
2494+ return len(soup.find_all('span', class_dict))
2495
2496 def contains_one_link_to_diff(self, html_or_soup, package_diff):
2497 """Return whether the html contains a link to the diff content."""
2498@@ -380,7 +380,7 @@ class DistroSeriesDifferenceTemplateTestCase(TestCaseWithFactory):
2499 soup = BeautifulSoup(html_or_soup)
2500 else:
2501 soup = html_or_soup
2502- return 1 == len(soup.findAll(
2503+ return 1 == len(soup.find_all(
2504 'a', href=package_diff.diff_content.http_url))
2505
2506 def test_both_request_diff_texts_rendered(self):
2507@@ -435,7 +435,7 @@ class DistroSeriesDifferenceTemplateTestCase(TestCaseWithFactory):
2508 # The diff has a css_class class.
2509 self.assertEqual(
2510 1,
2511- len(soup.findAll('span', {'class': re.compile(css_class)})))
2512+ len(soup.find_all('span', {'class': re.compile(css_class)})))
2513
2514 def test_parent_source_diff_rendering_diff_no_link(self):
2515 # The status of the package is shown if the parent package diff is
2516@@ -459,7 +459,7 @@ class DistroSeriesDifferenceTemplateTestCase(TestCaseWithFactory):
2517 # The diff has a css_class class.
2518 self.assertEqual(
2519 1,
2520- len(soup.findAll('span', {'class': re.compile(css_class)})))
2521+ len(soup.find_all('span', {'class': re.compile(css_class)})))
2522
2523 def test_source_diff_rendering_no_source(self):
2524 # If there is no source pub for this difference, then we don't
2525@@ -511,9 +511,9 @@ class DistroSeriesDifferenceTemplateTestCase(TestCaseWithFactory):
2526 soup = BeautifulSoup(view())
2527
2528 self.assertEqual(
2529- 1, len(soup.findAll('p', text="I'm working on this.")))
2530+ 1, len(soup.find_all('p', text="I'm working on this.")))
2531 self.assertEqual(
2532- 1, len(soup.findAll('p', text="Here's another comment.")))
2533+ 1, len(soup.find_all('p', text="Here's another comment.")))
2534
2535 def test_last_common_version_is_linked(self):
2536 # The "Last Common Version" version text should link to the
2537@@ -555,7 +555,7 @@ class DistroSeriesDifferenceTemplateTestCase(TestCaseWithFactory):
2538 soup = BeautifulSoup(view_content)
2539
2540 self.assertEqual(
2541- 1, len(soup.findAll('div', {'class': 'blacklist-options'})))
2542+ 1, len(soup.find_all('div', {'class': 'blacklist-options'})))
2543
2544 def test_blacklist_options_disabled(self):
2545 # Blacklist options are disabled to the users who are *not* archive
2546@@ -568,7 +568,7 @@ class DistroSeriesDifferenceTemplateTestCase(TestCaseWithFactory):
2547
2548 self.assertEqual(
2549 1,
2550- len(soup.findAll('div', {'class': 'blacklist-options-disabled'})))
2551+ len(soup.find_all('div', {'class': 'blacklist-options-disabled'})))
2552
2553 def test_blacklist_options_initial_values_none(self):
2554 ds_diff = self.factory.makeDistroSeriesDifference()
2555diff --git a/lib/lp/registry/browser/tests/test_product.py b/lib/lp/registry/browser/tests/test_product.py
2556index 70a99ea..235fffd 100644
2557--- a/lib/lp/registry/browser/tests/test_product.py
2558+++ b/lib/lp/registry/browser/tests/test_product.py
2559@@ -1056,7 +1056,7 @@ class TestProductSet(BrowserTestCase):
2560 results = [
2561 re.sub('\nregistered\n.*', '', extract_text(td))
2562 for td in find_tag_by_id(
2563- browser.contents, 'latest-registered').findAll('td')]
2564+ browser.contents, 'latest-registered').find_all('td')]
2565 self.assertIn(public.display_name, results)
2566 self.assertIn(policy_granted.display_name, results)
2567 self.assertNotIn(artifact_granted.display_name, results)
2568@@ -1104,7 +1104,7 @@ class TestProductSet(BrowserTestCase):
2569 expected_results,
2570 [extract_text(td)
2571 for td in find_tag_by_id(
2572- browser.contents, 'search-results').findAll('td')])
2573+ browser.contents, 'search-results').find_all('td')])
2574
2575
2576 class TestProductSetBranchView(TestCaseWithFactory):
2577diff --git a/lib/lp/registry/doc/product-widgets.txt b/lib/lp/registry/doc/product-widgets.txt
2578index 35d4471..b656e51 100644
2579--- a/lib/lp/registry/doc/product-widgets.txt
2580+++ b/lib/lp/registry/doc/product-widgets.txt
2581@@ -314,7 +314,7 @@ One licence, the GNU GPL v2, is selected.
2582
2583 >>> def print_checked_items(html, links=False):
2584 ... soup = BeautifulSoup(html)
2585- ... for label in soup.findAll('label'):
2586+ ... for label in soup.find_all('label'):
2587 ... if not isinstance(label.next, Tag):
2588 ... continue
2589 ... if label.next.get('checked'):
2590diff --git a/lib/lp/registry/stories/announcements/xx-announcements.txt b/lib/lp/registry/stories/announcements/xx-announcements.txt
2591index 082256a..9296fb6 100644
2592--- a/lib/lp/registry/stories/announcements/xx-announcements.txt
2593+++ b/lib/lp/registry/stories/announcements/xx-announcements.txt
2594@@ -280,7 +280,7 @@ page that any user can navigate.
2595 >>> print(extract_text(content.h1))
2596 Derby announcement headline
2597
2598- >>> print(extract_text(content.findAll('p')[1]))
2599+ >>> print(extract_text(content.find_all('p')[1]))
2600 Derby announcement summary
2601
2602 >>> anon_browser.getLink("Read all announcements").click()
2603diff --git a/lib/lp/registry/stories/distributionmirror/xx-distribution-mirrors.txt b/lib/lp/registry/stories/distributionmirror/xx-distribution-mirrors.txt
2604index b1528b3..f288178 100644
2605--- a/lib/lp/registry/stories/distributionmirror/xx-distribution-mirrors.txt
2606+++ b/lib/lp/registry/stories/distributionmirror/xx-distribution-mirrors.txt
2607@@ -11,7 +11,7 @@ on their status and content.
2608 ... header = mirrors_table.find('tr')
2609 ... country = extract_text(header.find('th'))
2610 ... mirrors = []
2611- ... for tr in header.findNextSiblings('tr'):
2612+ ... for tr in header.find_next_siblings('tr'):
2613 ... if 'head' in str(tr.attrs):
2614 ... print("%s: %s" % (country, pretty(mirrors)))
2615 ... country = extract_text(tr.find('th'))
2616@@ -23,7 +23,7 @@ on their status and content.
2617 ... # from different countries, so we'll just skip it.
2618 ... pass
2619 ... else:
2620- ... tds = tuple([extract_text(td) for td in tr.findAll('td')])
2621+ ... tds = tuple([extract_text(td) for td in tr.find_all('td')])
2622 ... mirrors.append(tds)
2623
2624 Official mirrors
2625diff --git a/lib/lp/registry/stories/milestone/object-milestones.txt b/lib/lp/registry/stories/milestone/object-milestones.txt
2626index 5eaf227..0305466 100644
2627--- a/lib/lp/registry/stories/milestone/object-milestones.txt
2628+++ b/lib/lp/registry/stories/milestone/object-milestones.txt
2629@@ -13,11 +13,11 @@ function will print them out:
2630 ... if table is None:
2631 ... return None
2632 ... result = []
2633- ... for tr in table.findAll('tr'):
2634+ ... for tr in table.find_all('tr'):
2635 ... milestone_date = tr.find('span')
2636 ... if len(milestone_date.contents) > 0:
2637 ... # Just make sure we don't print an actual date.
2638- ... milestone_date.contents[0].replaceWith('A date')
2639+ ... milestone_date.contents[0].replace_with('A date')
2640 ... result.append(extract_text(tr))
2641 ... return '\n'.join(result)
2642
2643@@ -26,9 +26,9 @@ function will print them out:
2644 ... if portlet is None:
2645 ... return None
2646 ... result = []
2647- ... for tr in portlet.find('table').findAll('tr'):
2648+ ... for tr in portlet.find('table').find_all('tr'):
2649 ... result.append(
2650- ... ' '.join(text.strip() for text in tr.findAll(text=True)))
2651+ ... ' '.join(text.strip() for text in tr.find_all(text=True)))
2652 ... return '\n'.join(result)
2653
2654
2655@@ -361,7 +361,7 @@ listing:
2656
2657 Each bugtask has one or more badges.
2658
2659- >>> print(bug_table.findAll('tr')[1])
2660+ >>> print(bug_table.find_all('tr')[1])
2661 <tr>...Test Bug 1...<a...alt="milestone test-milestone"...
2662 class="sprite milestone"...>...
2663
2664diff --git a/lib/lp/registry/stories/person/xx-admin-person-review.txt b/lib/lp/registry/stories/person/xx-admin-person-review.txt
2665index bc2e2f6..e191f41 100644
2666--- a/lib/lp/registry/stories/person/xx-admin-person-review.txt
2667+++ b/lib/lp/registry/stories/person/xx-admin-person-review.txt
2668@@ -61,7 +61,7 @@ The +reviewaccount page displays account information that is normally
2669 hidden from the UI.
2670
2671 >>> content = find_main_content(expert_browser.contents)
2672- >>> for tr in content.find(id='summary').findAll('tr'):
2673+ >>> for tr in content.find(id='summary').find_all('tr'):
2674 ... print(extract_text(tr))
2675 Created: 2005-06-06
2676 Creation reason: Created by the owner themselves, coming from Launchpad.
2677diff --git a/lib/lp/registry/stories/person/xx-person-edit-jabber-ids.txt b/lib/lp/registry/stories/person/xx-person-edit-jabber-ids.txt
2678index f2a6112..72666ec 100644
2679--- a/lib/lp/registry/stories/person/xx-person-edit-jabber-ids.txt
2680+++ b/lib/lp/registry/stories/person/xx-person-edit-jabber-ids.txt
2681@@ -45,7 +45,7 @@ it will be associated with their account.
2682
2683 >>> def show_jabberids(browser):
2684 ... tags = find_tag_by_id(browser.contents, 'jabber-ids')
2685- ... for dd in tags.findAll('dd'):
2686+ ... for dd in tags.find_all('dd'):
2687 ... print(extract_text(dd))
2688
2689 >>> show_jabberids(user_browser)
2690diff --git a/lib/lp/registry/stories/person/xx-person-home.txt b/lib/lp/registry/stories/person/xx-person-home.txt
2691index fab8a67..28a99ab 100644
2692--- a/lib/lp/registry/stories/person/xx-person-home.txt
2693+++ b/lib/lp/registry/stories/person/xx-person-home.txt
2694@@ -188,9 +188,9 @@ most active and also the areas in which they worked on each project.
2695
2696 >>> anon_browser.open('http://launchpad.test/~name16')
2697 >>> table = find_tag_by_id(anon_browser.contents, 'contributions')
2698- >>> for tr in table.findAll('tr'):
2699+ >>> for tr in table.find_all('tr'):
2700 ... print(tr.find('th').find('a').decode_contents())
2701- ... for td in tr.findAll('td'):
2702+ ... for td in tr.find_all('td'):
2703 ... img = td.find('img')
2704 ... if img is not None:
2705 ... print("\t", img['title'])
2706diff --git a/lib/lp/registry/stories/person/xx-person-karma.txt b/lib/lp/registry/stories/person/xx-person-karma.txt
2707index 8c1c741..09c759d 100644
2708--- a/lib/lp/registry/stories/person/xx-person-karma.txt
2709+++ b/lib/lp/registry/stories/person/xx-person-karma.txt
2710@@ -24,14 +24,14 @@ The total karma points is also a link to the person's karma summary page.
2711 Any user can see the categories that a user has earned karma in.
2712
2713 >>> content = find_main_content(anon_browser.contents)
2714- >>> for row in find_tag_by_id(content, 'karmapoints').findAll('tr'):
2715+ >>> for row in find_tag_by_id(content, 'karmapoints').find_all('tr'):
2716 ... print(extract_text(row))
2717 Bug Management 94
2718 Specification Tracking 44
2719
2720 Any user can see that a user has latest actions.
2721
2722- >>> for row in find_tag_by_id(content, 'karmaactions').findAll('tr'):
2723+ >>> for row in find_tag_by_id(content, 'karmaactions').find_all('tr'):
2724 ... print(extract_text(row))
2725 Date Action
2726 2001-11-02 Registered Specification
2727@@ -55,7 +55,7 @@ a that user's last karma actions
2728 >>> print(extract_text(find_tag_by_id(content, 'no-karma')))
2729 Karl Tilbury's karma has expired.
2730
2731- >>> for row in find_tag_by_id(content, 'karmaactions').findAll('tr'):
2732+ >>> for row in find_tag_by_id(content, 'karmaactions').find_all('tr'):
2733 ... print(extract_text(row))
2734 Date Action
2735 2001-08-09 New Bug Filed
2736diff --git a/lib/lp/registry/stories/person/xx-person-projects.txt b/lib/lp/registry/stories/person/xx-person-projects.txt
2737index 89a323c..ed5fd27 100644
2738--- a/lib/lp/registry/stories/person/xx-person-projects.txt
2739+++ b/lib/lp/registry/stories/person/xx-person-projects.txt
2740@@ -7,7 +7,7 @@ team.
2741 >>> anon_browser.open('http://launchpad.test/~ubuntu-team')
2742 >>> related_projects = find_tag_by_id(
2743 ... anon_browser.contents, 'portlet-related-projects')
2744- >>> for tr in related_projects.findAll('tr'):
2745+ >>> for tr in related_projects.find_all('tr'):
2746 ... print(extract_text(tr))
2747 Ubuntu
2748 ubuntutest
2749diff --git a/lib/lp/registry/stories/person/xx-person-subscriptions.txt b/lib/lp/registry/stories/person/xx-person-subscriptions.txt
2750index 8546cb1..97c5d1e 100644
2751--- a/lib/lp/registry/stories/person/xx-person-subscriptions.txt
2752+++ b/lib/lp/registry/stories/person/xx-person-subscriptions.txt
2753@@ -169,8 +169,8 @@ followed by a link to edit the subscription.
2754
2755 >>> subscriptions = find_tag_by_id(
2756 ... admin_browser.contents, 'structural-subscriptions')
2757- >>> for subscription in subscriptions.findAll("li"):
2758- ... structure_link, modify_link = subscription.findAll("a")[:2]
2759+ >>> for subscription in subscriptions.find_all("li"):
2760+ ... structure_link, modify_link = subscription.find_all("a")[:2]
2761 ... print("%s <%s>" % (
2762 ... extract_text(structure_link), structure_link.get("href")))
2763 ... print("--> %s" % modify_link.get("href"))
2764@@ -186,7 +186,7 @@ permission to modify those subscriptions.
2765 ... "http://launchpad.test/~name16/+structural-subscriptions")
2766 >>> subscriptions = find_tag_by_id(
2767 ... subscriber_browser.contents, 'structural-subscriptions')
2768- >>> for subscription in subscriptions.findAll("li"):
2769+ >>> for subscription in subscriptions.find_all("li"):
2770 ... structure_link = subscription.find("a")
2771 ... print("%s <%s>" % (
2772 ... extract_text(structure_link), structure_link.get("href")))
2773@@ -220,7 +220,7 @@ subscription filter.
2774 >>> def show_create_links(browser):
2775 ... subscriptions = find_tag_by_id(
2776 ... browser.contents, 'structural-subscriptions')
2777- ... for subscription in subscriptions.findAll("li"):
2778+ ... for subscription in subscriptions.find_all("li"):
2779 ... structure_link = subscription.find("a")
2780 ... print(extract_text(structure_link))
2781 ... create_text = subscription.find(text=re.compile("Create"))
2782@@ -272,7 +272,7 @@ filters are shown with a message stating that there is no filtering.
2783 ... "+me/+structural-subscriptions")
2784 ... subscriptions = find_tag_by_id(
2785 ... nigel_browser.contents, 'structural-subscriptions')
2786- ... for subscription in subscriptions.findAll("li"):
2787+ ... for subscription in subscriptions.find_all("li"):
2788 ... print(extract_text(subscription.p))
2789 ... if subscription.dl is not None:
2790 ... print(extract_text(subscription.dl))
2791diff --git a/lib/lp/registry/stories/pillar/xx-pillar-sprints.txt b/lib/lp/registry/stories/pillar/xx-pillar-sprints.txt
2792index 6e24e3b..edb6888 100644
2793--- a/lib/lp/registry/stories/pillar/xx-pillar-sprints.txt
2794+++ b/lib/lp/registry/stories/pillar/xx-pillar-sprints.txt
2795@@ -6,7 +6,7 @@ all events relevant to that pillar.
2796 >>> import re
2797 >>> def print_sprints(contents):
2798 ... maincontent = find_tag_by_id(contents, 'maincontent')
2799- ... for link in maincontent.findAll('a'):
2800+ ... for link in maincontent.find_all('a'):
2801 ... if re.search('/sprints/[a-z0-9]', link['href']) is not None:
2802 ... print(link.decode_contents())
2803
2804diff --git a/lib/lp/registry/stories/product/xx-launchpad-project-search.txt b/lib/lp/registry/stories/product/xx-launchpad-project-search.txt
2805index 1a22992..e3f6b8b 100644
2806--- a/lib/lp/registry/stories/product/xx-launchpad-project-search.txt
2807+++ b/lib/lp/registry/stories/product/xx-launchpad-project-search.txt
2808@@ -98,5 +98,5 @@ A similar page is available for only searching project groups.
2809 The search results contains only project-groups.
2810
2811 >>> print(extract_text(
2812- ... find_main_content(anon_browser.contents).findAll('p')[1]))
2813+ ... find_main_content(anon_browser.contents).find_all('p')[1]))
2814 1 project group found matching ...gnome...
2815diff --git a/lib/lp/registry/stories/product/xx-product-code-trunk.txt b/lib/lp/registry/stories/product/xx-product-code-trunk.txt
2816index 04ba410..84fb002 100644
2817--- a/lib/lp/registry/stories/product/xx-product-code-trunk.txt
2818+++ b/lib/lp/registry/stories/product/xx-product-code-trunk.txt
2819@@ -26,7 +26,7 @@ Make revisions for the branch so it has a codebrowse link.
2820 ... dev_focus = find_tag_by_id(browser.contents, 'development-focus')
2821 ... print(extract_text(dev_focus))
2822 ... print("Links:")
2823- ... for a in dev_focus.findAll('a'):
2824+ ... for a in dev_focus.find_all('a'):
2825 ... for content in a.contents:
2826 ... print(content)
2827 ... title = a.get('title', '')
2828@@ -40,14 +40,14 @@ Make revisions for the branch so it has a codebrowse link.
2829 ... except TypeError:
2830 ... return
2831 ... print("Links:")
2832- ... for a in code_trunk.findAll('a'):
2833+ ... for a in code_trunk.find_all('a'):
2834 ... for content in a.contents:
2835 ... print(content)
2836 ... title = a.get('title', '')
2837 ... print("%s (%s)" % (title, a['href']))
2838 >>> def print_involvement_portlet(browser):
2839 ... involvement = find_tag_by_id(browser.contents, 'involvement')
2840- ... for a in involvement.findAll('a'):
2841+ ... for a in involvement.find_all('a'):
2842 ... for content in a.contents:
2843 ... print(content)
2844 ... print(a['href'])
2845diff --git a/lib/lp/registry/stories/product/xx-product-files.txt b/lib/lp/registry/stories/product/xx-product-files.txt
2846index 11386bb..04f7fc8 100644
2847--- a/lib/lp/registry/stories/product/xx-product-files.txt
2848+++ b/lib/lp/registry/stories/product/xx-product-files.txt
2849@@ -261,7 +261,7 @@ user to see.
2850
2851 >>> anon_browser.open('http://launchpad.test/firefox/+download')
2852 >>> content = find_main_content(anon_browser.contents)
2853- >>> for tr in content.findAll('table')[1].findAll('tr'):
2854+ >>> for tr in content.find_all('table')[1].find_all('tr'):
2855 ... print(extract_text(tr))
2856 File Description Downloads
2857 bar.txt (md5) Bar installer -
2858@@ -275,7 +275,7 @@ an admin can also delete a release file.
2859 >>> checkbox = admin_browser.getControl(name='checkbox_0')
2860 >>> checkbox.value = checkbox.options
2861 >>> table = find_tag_by_id(admin_browser.contents, 'downloads')
2862- >>> for tr in table.findAll('tr'):
2863+ >>> for tr in table.find_all('tr'):
2864 ... print(extract_text(tr))
2865 File Description Downloads Delete
2866 bar.txt (md5) Bar installer -
2867@@ -286,7 +286,7 @@ an admin can also delete a release file.
2868 >>> print_feedback_messages(admin_browser.contents)
2869 1 file has been deleted.
2870 >>> table = find_tag_by_id(admin_browser.contents, 'downloads')
2871- >>> for tr in table.findAll('tr'):
2872+ >>> for tr in table.find_all('tr'):
2873 ... print(extract_text(tr))
2874 File Description Downloads Delete
2875 foo.txt (md5, sig) Foo installer -
2876@@ -386,9 +386,9 @@ are listed within series in reverse chronological order, except
2877 >>> firefox_owner.url
2878 'http://launchpad.test/firefox/+download'
2879 >>> content = find_main_content(firefox_owner.contents)
2880- >>> rows = content.findAll('tr')
2881+ >>> rows = content.find_all('tr')
2882 >>> for row in rows[1:]:
2883- ... a_list = row.findAll('a')
2884+ ... a_list = row.find_all('a')
2885 ... if len(a_list) > 0:
2886 ... print(a_list[0].string)
2887 firefox_0.9.2.orig.tar.gz
2888@@ -447,9 +447,9 @@ Ensure the file is no longer listed.
2889 >>> firefox_owner.url
2890 'http://launchpad.test/firefox/+download'
2891 >>> content = find_main_content(firefox_owner.contents)
2892- >>> rows = content.findAll('tr')
2893+ >>> rows = content.find_all('tr')
2894 >>> for row in rows[1:]:
2895- ... a_list = row.findAll('a')
2896+ ... a_list = row.find_all('a')
2897 ... if len(a_list) > 0:
2898 ... print(a_list[0].string)
2899 firefox_0.9.2.orig.tar.gz
2900@@ -466,7 +466,7 @@ Non-administrators do not have the delete option.
2901
2902 >>> non_owner.open('http://launchpad.test/firefox/trunk/0.9')
2903 >>> table = find_tag_by_id(non_owner.contents, 'downloads')
2904- >>> for tr in table.findAll('tr'):
2905+ >>> for tr in table.find_all('tr'):
2906 ... print(extract_text(tr))
2907 File Description Downloads
2908 foo09.txt (md5) Foo09 installer -
2909@@ -485,7 +485,7 @@ so it is not shown.
2910
2911 >>> firefox_owner.open('http://launchpad.test/firefox/trunk/0.9')
2912 >>> table = find_tag_by_id(firefox_owner.contents, 'downloads')
2913- >>> for tr in table.findAll('tr'):
2914+ >>> for tr in table.find_all('tr'):
2915 ... print(extract_text(tr))
2916 File Description Downloads Delete
2917 foo09.txt (md5) Foo09 installer -
2918diff --git a/lib/lp/registry/stories/product/xx-product-index.txt b/lib/lp/registry/stories/product/xx-product-index.txt
2919index 28e7079..6aa8dc8 100644
2920--- a/lib/lp/registry/stories/product/xx-product-index.txt
2921+++ b/lib/lp/registry/stories/product/xx-product-index.txt
2922@@ -50,7 +50,7 @@ Let's check it out:
2923 >>> browser.open('http://launchpad.test/tomcat')
2924 >>> content = find_main_content(browser.contents)
2925 >>> external_links = find_tag_by_id(content, 'external-links')
2926- >>> for link in external_links.findAll('a'):
2927+ >>> for link in external_links.find_all('a'):
2928 ... print(extract_text(link), link['href'])
2929 Home page http://home.page/
2930 Sourceforge project http://sourceforge.net/projects/sf-tomcat
2931@@ -75,7 +75,7 @@ When the sourceforge URL is identical to the homepage, we omit the homepage:
2932 >>> browser.open('http://launchpad.test/tomcat')
2933 >>> content = find_main_content(browser.contents)
2934 >>> external_links = find_tag_by_id(content, 'external-links')
2935- >>> for link in external_links.findAll('a'):
2936+ >>> for link in external_links.find_all('a'):
2937 ... print(extract_text(link), link['href'])
2938 Sourceforge project http://sourceforge.net/projects/sf-tomcat
2939 Wiki http://wiki.url/
2940diff --git a/lib/lp/registry/stories/productseries/xx-productseries-index.txt b/lib/lp/registry/stories/productseries/xx-productseries-index.txt
2941index 7a4470c..55724b4 100644
2942--- a/lib/lp/registry/stories/productseries/xx-productseries-index.txt
2943+++ b/lib/lp/registry/stories/productseries/xx-productseries-index.txt
2944@@ -50,7 +50,7 @@ Any user can subscribe to bug mail via the link on the page.
2945
2946 The series page lists the milestones and releases for the series.
2947
2948- >>> rows = find_tag_by_id(content, 'series-trunk').findAll('tr')
2949+ >>> rows = find_tag_by_id(content, 'series-trunk').find_all('tr')
2950 >>> for row in rows[0:2]:
2951 ... print(extract_text(row))
2952 Version Expected Released Summary
2953@@ -60,7 +60,7 @@ The driver can see a link to set the expected date.
2954
2955 >>> driver_content = find_main_content(driver_browser.contents)
2956 >>> driver_rows = find_tag_by_id(
2957- ... driver_content, 'series-trunk').findAll('tr')
2958+ ... driver_content, 'series-trunk').find_all('tr')
2959 >>> for row in driver_rows[0:2]:
2960 ... print(extract_text(row))
2961 Version Expected Released Summary
2962diff --git a/lib/lp/registry/stories/team/xx-team-claim.txt b/lib/lp/registry/stories/team/xx-team-claim.txt
2963index 5491e01..1fca7ec 100644
2964--- a/lib/lp/registry/stories/team/xx-team-claim.txt
2965+++ b/lib/lp/registry/stories/team/xx-team-claim.txt
2966@@ -84,7 +84,7 @@ claim process the team's owner.
2967 >>> from lp.services.beautifulsoup import BeautifulSoup
2968 >>> soup = BeautifulSoup(user_browser.contents)
2969 >>> print(extract_text(
2970- ... soup.find(attrs={'for': 'field.teamowner'}).findPrevious('tr')))
2971+ ... soup.find(attrs={'for': 'field.teamowner'}).find_previous('tr')))
2972 Team Owner: No Privileges Person...
2973
2974 >>> user_browser.getControl('Display Name').value = 'Ubuntu Doc Team'
2975diff --git a/lib/lp/registry/stories/teammembership/xx-teammembership.txt b/lib/lp/registry/stories/teammembership/xx-teammembership.txt
2976index acc2b9f..ff6f13d 100644
2977--- a/lib/lp/registry/stories/teammembership/xx-teammembership.txt
2978+++ b/lib/lp/registry/stories/teammembership/xx-teammembership.txt
2979@@ -211,12 +211,12 @@ be there at all.
2980 'http://launchpad.test/~myemail/+members'
2981
2982 >>> contents = anon_browser.contents
2983- >>> for link in find_tag_by_id(contents, 'activemembers').findAll('a'):
2984+ >>> for link in find_tag_by_id(contents, 'activemembers').find_all('a'):
2985 ... print(link.decode_contents())
2986 Karl Tilbury
2987 Sample Person
2988
2989- >>> for link in find_tag_by_id(contents, 'proposedmembers').findAll('a'):
2990+ >>> for link in find_tag_by_id(contents, 'proposedmembers').find_all('a'):
2991 ... print(link.decode_contents())
2992 Colin Watson
2993 James Blackwell
2994@@ -231,7 +231,7 @@ have been invited.
2995
2996 >>> def print_members(contents, type):
2997 ... table = find_tag_by_id(contents, type)
2998- ... for link in table.findAll('a'):
2999+ ... for link in table.find_all('a'):
3000 ... link_contents = link.decode_contents()
3001 ... if link_contents != 'Edit' and not link.find('img'):
3002 ... print(link_contents)
3003diff --git a/lib/lp/registry/tests/test_product.py b/lib/lp/registry/tests/test_product.py
3004index 0f04a93..80f7edd 100644
3005--- a/lib/lp/registry/tests/test_product.py
3006+++ b/lib/lp/registry/tests/test_product.py
3007@@ -1437,9 +1437,9 @@ class TestProductFiles(TestCase):
3008 [u"Your file 'foo\xa5.txt' has been uploaded."])
3009 firefox_owner.open('http://launchpad.test/firefox/+download')
3010 content = find_main_content(firefox_owner.contents)
3011- rows = content.findAll('tr')
3012+ rows = content.find_all('tr')
3013
3014- a_list = rows[-1].findAll('a')
3015+ a_list = rows[-1].find_all('a')
3016 # 1st row
3017 a_element = a_list[0]
3018 self.assertEqual(
3019diff --git a/lib/lp/services/feeds/feed.py b/lib/lp/services/feeds/feed.py
3020index 352e540..e49e988 100644
3021--- a/lib/lp/services/feeds/feed.py
3022+++ b/lib/lp/services/feeds/feed.py
3023@@ -292,7 +292,7 @@ class FeedTypedData:
3024 # or they will try be served from http://feeds.launchpad.net,
3025 # which will not work.
3026 soup = BeautifulSoup(self._content)
3027- a_tags = soup.findAll('a')
3028+ a_tags = soup.find_all('a')
3029 for a_tag in a_tags:
3030 if a_tag['href'].startswith('/'):
3031 a_tag['href'] = urljoin(self.root_url, a_tag['href'])
3032diff --git a/lib/lp/services/feeds/stories/xx-links.txt b/lib/lp/services/feeds/stories/xx-links.txt
3033index 54f928a..ae5adf4 100644
3034--- a/lib/lp/services/feeds/stories/xx-links.txt
3035+++ b/lib/lp/services/feeds/stories/xx-links.txt
3036@@ -14,7 +14,7 @@ displays the most recent announcements for all the projects.
3037 >>> from lp.services.beautifulsoup import BeautifulSoup
3038 >>> browser.open('http://launchpad.test/')
3039 >>> soup = BeautifulSoup(browser.contents)
3040- >>> soup.head.findAll('link', type='application/atom+xml')
3041+ >>> soup.head.find_all('link', type='application/atom+xml')
3042 [<link href="http://feeds.launchpad.test/announcements.atom"
3043 rel="alternate" title="All Announcements"
3044 type="application/atom+xml"/>]
3045@@ -25,7 +25,7 @@ feed.
3046
3047 >>> browser.open('http://launchpad.test/+announcements')
3048 >>> soup = BeautifulSoup(browser.contents)
3049- >>> soup.head.findAll('link', type='application/atom+xml')
3050+ >>> soup.head.find_all('link', type='application/atom+xml')
3051 [<link href="http://feeds.launchpad.test/announcements.atom"
3052 rel="alternate" title="All Announcements"
3053 type="application/atom+xml"/>]
3054@@ -37,7 +37,7 @@ atom feed for that one bug.
3055
3056 >>> browser.open('http://bugs.launchpad.test/firefox/+bug/1')
3057 >>> soup = BeautifulSoup(browser.contents)
3058- >>> soup.head.findAll('link', type='application/atom+xml')
3059+ >>> soup.head.find_all('link', type='application/atom+xml')
3060 [<link href="http://feeds.launchpad.test/bugs/1/bug.atom"
3061 rel="alternate" title="Bug 1 Feed"
3062 type="application/atom+xml"/>]
3063@@ -59,7 +59,7 @@ But if the bug is private, there should be no link.
3064 http://bugs.launchpad.test/jokosher/+bug/14
3065
3066 >>> soup = BeautifulSoup(auth_browser.contents)
3067- >>> soup.head.findAll('link', type='application/atom+xml')
3068+ >>> soup.head.find_all('link', type='application/atom+xml')
3069 []
3070
3071 Even so, if they somehow manage to hack the url or use inline ajax editing of
3072@@ -79,7 +79,7 @@ branches.
3073
3074 >>> browser.open('http://launchpad.test/~stevea')
3075 >>> soup = BeautifulSoup(browser.contents)
3076- >>> soup.head.findAll('link', type='application/atom+xml')
3077+ >>> soup.head.find_all('link', type='application/atom+xml')
3078 [<link href="http://feeds.launchpad.test/~stevea/latest-bugs.atom"
3079 rel="alternate" title="Latest Bugs for Steve Alexander"
3080 type="application/atom+xml"/>,
3081@@ -95,7 +95,7 @@ not the branches link.
3082
3083 >>> browser.open('http://bugs.launchpad.test/~stevea')
3084 >>> soup = BeautifulSoup(browser.contents)
3085- >>> soup.head.findAll('link', type='application/atom+xml')
3086+ >>> soup.head.find_all('link', type='application/atom+xml')
3087 [<link href="http://feeds.launchpad.test/~stevea/latest-bugs.atom"
3088 rel="alternate" title="Latest Bugs for Steve Alexander"
3089 type="application/atom+xml"/>]
3090@@ -111,7 +111,7 @@ main product page.
3091
3092 >>> browser.open('http://launchpad.test/jokosher')
3093 >>> soup = BeautifulSoup(browser.contents)
3094- >>> soup.head.findAll('link', type='application/atom+xml')
3095+ >>> soup.head.find_all('link', type='application/atom+xml')
3096 [<link href="http://feeds.launchpad.test/jokosher/announcements.atom"
3097 rel="alternate" title="Announcements for Jokosher"
3098 type="application/atom+xml"/>,
3099@@ -129,7 +129,7 @@ Only bug feeds should be linked to on bugs.launchpad.test.
3100
3101 >>> browser.open('http://bugs.launchpad.test/jokosher')
3102 >>> soup = BeautifulSoup(browser.contents)
3103- >>> soup.head.findAll('link', type='application/atom+xml')
3104+ >>> soup.head.find_all('link', type='application/atom+xml')
3105 [<link href="http://feeds.launchpad.test/jokosher/latest-bugs.atom"
3106 rel="alternate" title="Latest Bugs for Jokosher"
3107 type="application/atom+xml"/>]
3108@@ -159,7 +159,7 @@ it must have quotes and html escaped.
3109 >>> logout()
3110 >>> browser.open('http://launchpad.test/bad-displayname')
3111 >>> soup = BeautifulSoup(browser.contents)
3112- >>> soup.head.findAll('link', type='application/atom+xml')
3113+ >>> soup.head.find_all('link', type='application/atom+xml')
3114 [<link href="http://feeds.launchpad.test/bad-displayname/announcements.atom"
3115 rel="alternate"
3116 title='Announcements for Bad displayname"&gt;&lt;script&gt;alert("h4x0r")&lt;/script&gt;'
3117@@ -187,7 +187,7 @@ on the main project group page.
3118
3119 >>> browser.open('http://launchpad.test/gnome')
3120 >>> soup = BeautifulSoup(browser.contents)
3121- >>> soup.head.findAll('link', type='application/atom+xml')
3122+ >>> soup.head.find_all('link', type='application/atom+xml')
3123 [<link href="http://feeds.launchpad.test/gnome/announcements.atom"
3124 rel="alternate" title="Announcements for GNOME"
3125 type="application/atom+xml"/>,
3126@@ -205,7 +205,7 @@ Only bug feeds should be linked to on bugs.launchpad.test.
3127
3128 >>> browser.open('http://bugs.launchpad.test/gnome')
3129 >>> soup = BeautifulSoup(browser.contents)
3130- >>> soup.head.findAll('link', type='application/atom+xml')
3131+ >>> soup.head.find_all('link', type='application/atom+xml')
3132 [<link href="http://feeds.launchpad.test/gnome/latest-bugs.atom"
3133 rel="alternate" title="Latest Bugs for GNOME"
3134 type="application/atom+xml"/>]
3135@@ -221,7 +221,7 @@ that the code does not display the atom feed link here inappropriately.
3136 ... '&field.status=Confirmed&field.status=Triaged'
3137 ... '&field.status=In+Progress&field.status=Fix+Committed')
3138 >>> soup = BeautifulSoup(browser.contents)
3139- >>> soup.head.findAll('link', type='application/atom+xml')
3140+ >>> soup.head.find_all('link', type='application/atom+xml')
3141 []
3142
3143
3144@@ -234,7 +234,7 @@ An announcements feed link should also be shown on the main distro page.
3145
3146 >>> browser.open('http://launchpad.test/ubuntu')
3147 >>> soup = BeautifulSoup(browser.contents)
3148- >>> soup.head.findAll('link', type='application/atom+xml')
3149+ >>> soup.head.find_all('link', type='application/atom+xml')
3150 [<link href="http://feeds.launchpad.test/ubuntu/announcements.atom"
3151 rel="alternate" title="Announcements for Ubuntu"
3152 type="application/atom+xml"/>,
3153@@ -246,7 +246,7 @@ Only bug feeds should be linked to on bugs.launchpad.test.
3154
3155 >>> browser.open('http://bugs.launchpad.test/ubuntu')
3156 >>> soup = BeautifulSoup(browser.contents)
3157- >>> soup.head.findAll('link', type='application/atom+xml')
3158+ >>> soup.head.find_all('link', type='application/atom+xml')
3159 [<link href="http://feeds.launchpad.test/ubuntu/latest-bugs.atom"
3160 rel="alternate" title="Latest Bugs for Ubuntu"
3161 type="application/atom+xml"/>]
3162@@ -259,7 +259,7 @@ show a link to the atom feed for that distroseries' latest bugs.
3163
3164 >>> browser.open('http://bugs.launchpad.test/ubuntu/hoary')
3165 >>> soup = BeautifulSoup(browser.contents)
3166- >>> soup.head.findAll('link', type='application/atom+xml')
3167+ >>> soup.head.find_all('link', type='application/atom+xml')
3168 [<link
3169 href="http://feeds.launchpad.test/ubuntu/hoary/latest-bugs.atom"
3170 rel="alternate" title="Latest Bugs for Hoary"
3171@@ -273,7 +273,7 @@ show a link to the atom feed for that product series' latest bugs.
3172
3173 >>> browser.open('http://bugs.launchpad.test/firefox/1.0')
3174 >>> soup = BeautifulSoup(browser.contents)
3175- >>> soup.head.findAll('link', type='application/atom+xml')
3176+ >>> soup.head.find_all('link', type='application/atom+xml')
3177 [<link href="http://feeds.launchpad.test/firefox/1.0/latest-bugs.atom"
3178 rel="alternate" title="Latest Bugs for 1.0"
3179 type="application/atom+xml"/>]
3180@@ -286,7 +286,7 @@ show a link to the atom feed for that source package's latest bugs.
3181
3182 >>> browser.open('http://bugs.launchpad.test/ubuntu/+source/cnews')
3183 >>> soup = BeautifulSoup(browser.contents)
3184- >>> soup.head.findAll('link', type='application/atom+xml')
3185+ >>> soup.head.find_all('link', type='application/atom+xml')
3186 [<link
3187 href="http://feeds.launchpad.test/ubuntu/+source/cnews/latest-bugs.atom"
3188 rel="alternate" title="Latest Bugs for cnews in Ubuntu"
3189@@ -300,7 +300,7 @@ to the atom feed for that project group's latest branches.
3190
3191 >>> browser.open('http://code.launchpad.test/mozilla')
3192 >>> soup = BeautifulSoup(browser.contents)
3193- >>> soup.head.findAll('link', type='application/atom+xml')
3194+ >>> soup.head.find_all('link', type='application/atom+xml')
3195 [<link
3196 href="http://feeds.launchpad.test/mozilla/branches.atom"
3197 rel="alternate" title="Latest Branches for The Mozilla Project"
3198@@ -318,7 +318,7 @@ to the atom feed for that product's latest branches.
3199
3200 >>> browser.open('http://code.launchpad.test/firefox')
3201 >>> soup = BeautifulSoup(browser.contents)
3202- >>> soup.head.findAll('link', type='application/atom+xml')
3203+ >>> soup.head.find_all('link', type='application/atom+xml')
3204 [<link href="http://feeds.launchpad.test/firefox/branches.atom"
3205 rel="alternate" title="Latest Branches for Mozilla Firefox"
3206 type="application/atom+xml"/>,
3207@@ -335,7 +335,7 @@ to the atom feed for that person's latest branches.
3208
3209 >>> browser.open('http://code.launchpad.test/~mark')
3210 >>> soup = BeautifulSoup(browser.contents)
3211- >>> soup.head.findAll('link', type='application/atom+xml')
3212+ >>> soup.head.find_all('link', type='application/atom+xml')
3213 [<link href="http://feeds.launchpad.test/~mark/branches.atom"
3214 rel="alternate" title="Latest Branches for Mark Shuttleworth"
3215 type="application/atom+xml"/>,
3216@@ -352,7 +352,7 @@ atom feed for that branch's revisions.
3217 >>> url = 'http://code.launchpad.test/~mark/firefox/release--0.9.1'
3218 >>> browser.open(url)
3219 >>> soup = BeautifulSoup(browser.contents)
3220- >>> soup.head.findAll('link', type='application/atom+xml')
3221+ >>> soup.head.find_all('link', type='application/atom+xml')
3222 [<link
3223 href="http://feeds.launchpad.test/~mark/firefox/release--0.9.1/branch.atom"
3224 rel="alternate"
3225@@ -368,7 +368,7 @@ But if the branch is private, there should be no link.
3226 >>> auth_browser.open(
3227 ... 'https://code.launchpad.test/~name12/landscape/feature-x')
3228 >>> soup = BeautifulSoup(auth_browser.contents)
3229- >>> soup.head.findAll('link', type='application/atom+xml')
3230+ >>> soup.head.find_all('link', type='application/atom+xml')
3231 []
3232
3233 Even so, if they somehow manage to hack the url, they are redirected to a page
3234diff --git a/lib/lp/services/oauth/doc/oauth-pages.txt b/lib/lp/services/oauth/doc/oauth-pages.txt
3235index 5b9cd98..c2ed07f 100644
3236--- a/lib/lp/services/oauth/doc/oauth-pages.txt
3237+++ b/lib/lp/services/oauth/doc/oauth-pages.txt
3238@@ -32,7 +32,7 @@ consumer's request to access Launchpad on their behalf.
3239 >>> def print_hidden_fields(html):
3240 ... soup = BeautifulSoup(
3241 ... html, parse_only=SoupStrainer(attrs={'type': 'hidden'}))
3242- ... for tag in soup.findAll(attrs={'type': 'hidden'}):
3243+ ... for tag in soup.find_all(attrs={'type': 'hidden'}):
3244 ... if tag['value']:
3245 ... print(tag['name'], tag['value'])
3246
3247diff --git a/lib/lp/services/oauth/stories/authorize-token.txt b/lib/lp/services/oauth/stories/authorize-token.txt
3248index 23f4911..a734ee1 100644
3249--- a/lib/lp/services/oauth/stories/authorize-token.txt
3250+++ b/lib/lp/services/oauth/stories/authorize-token.txt
3251@@ -59,7 +59,7 @@ This page contains one submit button for each item of OAuthPermission,
3252 except for 'Desktop Integration', which must be specifically requested.
3253
3254 >>> def print_access_levels(main_content):
3255- ... actions = main_content.findAll('input', attrs={'type': 'submit'})
3256+ ... actions = main_content.find_all('input', attrs={'type': 'submit'})
3257 ... for action in actions:
3258 ... print(action['value'])
3259
3260@@ -71,7 +71,7 @@ except for 'Desktop Integration', which must be specifically requested.
3261 Change Anything
3262
3263 >>> from lp.services.webapp.interfaces import OAuthPermission
3264- >>> actions = main_content.findAll('input', attrs={'type': 'submit'})
3265+ >>> actions = main_content.find_all('input', attrs={'type': 'submit'})
3266 >>> len(actions) == len(OAuthPermission.items) - 1
3267 True
3268
3269diff --git a/lib/lp/services/oauth/stories/managing-tokens.txt b/lib/lp/services/oauth/stories/managing-tokens.txt
3270index a75ad04..b90a301 100644
3271--- a/lib/lp/services/oauth/stories/managing-tokens.txt
3272+++ b/lib/lp/services/oauth/stories/managing-tokens.txt
3273@@ -49,31 +49,31 @@ keys stored in hidden <input>s as well as the button to revoke the
3274 authorization.
3275
3276 >>> li = find_tag_by_id(main_content, 'tokens').find('li')
3277- >>> for input in li.find('form').findAll('input'):
3278+ >>> for input in li.find('form').find_all('input'):
3279 ... print(input['name'], input['value'])
3280 consumer_key System-wide: Ubuntu (mycomputer)
3281 token_key ...
3282 token_type access_token
3283 revoke Revoke Authorization
3284
3285- >>> li2 = li.findNextSibling('li')
3286- >>> for input in li2.find('form').findAll('input'):
3287+ >>> li2 = li.find_next_sibling('li')
3288+ >>> for input in li2.find('form').find_all('input'):
3289 ... print(input['name'], input['value'])
3290 consumer_key foobar123451432
3291 token_key salgado-read-nonprivate
3292 token_type access_token
3293 revoke Revoke Authorization
3294
3295- >>> li3 = li2.findNext('li')
3296- >>> for input in li3.find('form').findAll('input'):
3297+ >>> li3 = li2.find_next('li')
3298+ >>> for input in li3.find('form').find_all('input'):
3299 ... print(input['name'], input['value'])
3300 consumer_key launchpad-library
3301 token_key salgado-change-anything
3302 token_type access_token
3303 revoke Revoke Authorization
3304
3305- >>> li4 = li3.findNext('li')
3306- >>> for input in li4.find('form').findAll('input'):
3307+ >>> li4 = li3.find_next('li')
3308+ >>> for input in li4.find('form').find_all('input'):
3309 ... print(input['name'], input['value'])
3310 consumer_key oauthconsumerkey...
3311 token_key ...
3312diff --git a/lib/lp/services/webapp/tests/test_login.py b/lib/lp/services/webapp/tests/test_login.py
3313index 732257e..ccb7bc7 100644
3314--- a/lib/lp/services/webapp/tests/test_login.py
3315+++ b/lib/lp/services/webapp/tests/test_login.py
3316@@ -521,7 +521,7 @@ class TestOpenIDCallbackView(TestCaseWithFactory):
3317 discharge_form = find_tag_by_id(html, 'discharge-form')
3318 self.assertEqual(form['starting_url'], discharge_form['action'])
3319 self.assertThat(
3320- [dict(tag.attrs) for tag in discharge_form.findAll('input')],
3321+ [dict(tag.attrs) for tag in discharge_form.find_all('input')],
3322 MatchesListwise([
3323 ContainsDict({
3324 'type': Equals('hidden'),
3325diff --git a/lib/lp/snappy/browser/widgets/tests/test_snaparchivewidget.py b/lib/lp/snappy/browser/widgets/tests/test_snaparchivewidget.py
3326index 20bd018..84a601d 100644
3327--- a/lib/lp/snappy/browser/widgets/tests/test_snaparchivewidget.py
3328+++ b/lib/lp/snappy/browser/widgets/tests/test_snaparchivewidget.py
3329@@ -269,7 +269,7 @@ class TestSnapArchiveWidget(WithScenarios, TestCaseWithFactory):
3330 self.assertIn("primary", self.widget.options)
3331 self.assertIn("ppa", self.widget.options)
3332 soup = BeautifulSoup(markup)
3333- fields = soup.findAll(["input", "select"], {"id": re.compile(".*")})
3334+ fields = soup.find_all(["input", "select"], {"id": re.compile(".*")})
3335 expected_ids = [
3336 "field.archive.option.primary",
3337 "field.archive.option.ppa",
3338diff --git a/lib/lp/snappy/browser/widgets/tests/test_snapbuildchannelswidget.py b/lib/lp/snappy/browser/widgets/tests/test_snapbuildchannelswidget.py
3339index b9231d7..201ad85 100644
3340--- a/lib/lp/snappy/browser/widgets/tests/test_snapbuildchannelswidget.py
3341+++ b/lib/lp/snappy/browser/widgets/tests/test_snapbuildchannelswidget.py
3342@@ -181,7 +181,7 @@ class TestSnapBuildChannelsWidget(TestCaseWithFactory):
3343 self.assertIsNotNone(self.widget.core20_widget)
3344 self.assertIsNotNone(self.widget.snapcraft_widget)
3345 soup = BeautifulSoup(markup)
3346- fields = soup.findAll(["input"], {"id": re.compile(".*")})
3347+ fields = soup.find_all(["input"], {"id": re.compile(".*")})
3348 expected_ids = [
3349 "field.auto_build_channels.core",
3350 "field.auto_build_channels.core18",
3351diff --git a/lib/lp/snappy/browser/widgets/tests/test_storechannelswidget.py b/lib/lp/snappy/browser/widgets/tests/test_storechannelswidget.py
3352index 32635d4..f6e85fa 100644
3353--- a/lib/lp/snappy/browser/widgets/tests/test_storechannelswidget.py
3354+++ b/lib/lp/snappy/browser/widgets/tests/test_storechannelswidget.py
3355@@ -282,7 +282,7 @@ class TestStoreChannelsWidget(TestCaseWithFactory):
3356 self.assertIsNotNone(self.widget.track_widget)
3357 self.assertIsNotNone(self.widget.risks_widget)
3358 soup = BeautifulSoup(markup)
3359- fields = soup.findAll(["input"], {"id": re.compile(".*")})
3360+ fields = soup.find_all(["input"], {"id": re.compile(".*")})
3361 expected_ids = [
3362 "field.channels.risks.%d" % i for i in range(len(self.risks))]
3363 expected_ids.append("field.channels.track")
3364diff --git a/lib/lp/soyuz/browser/tests/test_archive_packages.py b/lib/lp/soyuz/browser/tests/test_archive_packages.py
3365index 3bbff33..fb0c062 100644
3366--- a/lib/lp/soyuz/browser/tests/test_archive_packages.py
3367+++ b/lib/lp/soyuz/browser/tests/test_archive_packages.py
3368@@ -458,7 +458,7 @@ class TestPPAPackagesJobNotifications(TestCaseWithFactory):
3369 )
3370 self.assertThat(html, packages_matches)
3371 self.assertEqual(
3372- [], BeautifulSoup(html).findAll(
3373+ [], BeautifulSoup(html).find_all(
3374 'span', text=re.compile('Showing 5 of .')))
3375
3376 def test_job_notifications_display_multiple_is_capped(self):
3377@@ -468,7 +468,7 @@ class TestPPAPackagesJobNotifications(TestCaseWithFactory):
3378 self.archive, "+packages", principal=self.archive.owner)
3379 soup = BeautifulSoup(view.render())
3380 self.assertEqual([],
3381- soup.findAll(
3382+ soup.find_all(
3383 'div', attrs={'class': 'pending-job', 'job_id': jobs[-1].id}))
3384 showing_tags = soup.find_all(
3385 'span', text=re.compile('Showing 5 of .'))
3386diff --git a/lib/lp/soyuz/stories/ppa/xx-ppa-packages.txt b/lib/lp/soyuz/stories/ppa/xx-ppa-packages.txt
3387index 296b971..21cd1a5 100644
3388--- a/lib/lp/soyuz/stories/ppa/xx-ppa-packages.txt
3389+++ b/lib/lp/soyuz/stories/ppa/xx-ppa-packages.txt
3390@@ -88,7 +88,7 @@ The detailed Packages list
3391 >>> def print_archive_package_rows(contents):
3392 ... package_table = find_tag_by_id(
3393 ... contents, 'packages_list')
3394- ... for ppa_row in package_table.findChildren('tr'):
3395+ ... for ppa_row in package_table.find_all('tr'):
3396 ... print(extract_text(ppa_row))
3397
3398 >>> print_archive_package_rows(anon_browser.contents)
3399@@ -418,10 +418,10 @@ Anyone can see the build status for package in Celso's PPA.
3400
3401 >>> def print_build_status(contents):
3402 ... rows = find_tags_by_class(contents, 'archive_package_row')
3403- ... headers = rows[0].findAll('th')
3404+ ... headers = rows[0].find_all('th')
3405 ... print(extract_text(headers[0]), extract_text(headers[-1]))
3406 ... for row in rows[1:]:
3407- ... columns = row.findAll('td')
3408+ ... columns = row.find_all('td')
3409 ... name = extract_text(columns[0])
3410 ... built_icon = columns[-1].img['src']
3411 ... built_text = columns[-1].a
3412diff --git a/lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt b/lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt
3413index 7da7244..cb57997 100644
3414--- a/lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt
3415+++ b/lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt
3416@@ -333,7 +333,7 @@ The source packages list is presented publicly.
3417 >>> def print_archive_package_rows(contents):
3418 ... package_table = find_tag_by_id(
3419 ... anon_browser.contents, 'packages_list')
3420- ... for ppa_row in package_table.findChildren('tr'):
3421+ ... for ppa_row in package_table.find_all('tr'):
3422 ... print(extract_text(ppa_row))
3423
3424 >>> print_archive_package_rows(anon_browser.contents)
3425diff --git a/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt b/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt
3426index 7a0c950..beb1430 100644
3427--- a/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt
3428+++ b/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt
3429@@ -103,7 +103,7 @@ For SourcePackage, it's only possible to filter by state.
3430 The source package default state is "all states":
3431
3432 >>> soup = find_main_content(anon_browser.contents)
3433- >>> [results] = soup.findAll(attrs={'selected': 'selected'})
3434+ >>> [results] = soup.find_all(attrs={'selected': 'selected'})
3435 >>> print(extract_text(results))
3436 All states
3437
3438diff --git a/lib/lp/soyuz/stories/soyuz/xx-distroarchseries-binpackages.txt b/lib/lp/soyuz/stories/soyuz/xx-distroarchseries-binpackages.txt
3439index c16c379..ab9dc39 100644
3440--- a/lib/lp/soyuz/stories/soyuz/xx-distroarchseries-binpackages.txt
3441+++ b/lib/lp/soyuz/stories/soyuz/xx-distroarchseries-binpackages.txt
3442@@ -31,7 +31,7 @@ this architecture:
3443 Published on 2006-04-11
3444 2005-06-18 00:00:00 UTC Published...Warty i386 release main base Extra 0.9
3445 Published on 2005-06-18
3446- >>> print(table.findAll("tr")[2].td["colspan"])
3447+ >>> print(table.find_all("tr")[2].td["colspan"])
3448 10
3449
3450 It also provides a link to the currently published version:
3451diff --git a/lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt b/lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt
3452index 0769ed2..05f49cf 100644
3453--- a/lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt
3454+++ b/lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt
3455@@ -49,7 +49,7 @@ about Firefox's publishing history.
3456 2006-02-13 12:19:00 UTC Published Warty release main web 0.9
3457 Published on 2006-02-13
3458 2004-09-27 11:57:13 UTC Pending Warty release main editors 0.9
3459- >>> print(table.findAll("tr")[2].td["colspan"])
3460+ >>> print(table.find_all("tr")[2].td["colspan"])
3461 8
3462
3463 Jump back to the DistributionSourcePackage page to continue the tests:
3464diff --git a/lib/lp/soyuz/stories/soyuz/xx-packagepublishinghistory.txt b/lib/lp/soyuz/stories/soyuz/xx-packagepublishinghistory.txt
3465index 6fdba84..dd60f1c 100644
3466--- a/lib/lp/soyuz/stories/soyuz/xx-packagepublishinghistory.txt
3467+++ b/lib/lp/soyuz/stories/soyuz/xx-packagepublishinghistory.txt
3468@@ -25,7 +25,7 @@ shows the complete history of a package in all series.
3469 ... UTC Published Breezy ... release main base 666
3470 Created ... ago by Foo Bar
3471 Published ... ago
3472- >>> print(table.findAll("tr")[2].td["colspan"])
3473+ >>> print(table.find_all("tr")[2].td["colspan"])
3474 8
3475
3476 Copy the package to a new distribution named "foo-distro". The publishing
3477diff --git a/lib/lp/soyuz/stories/soyuz/xx-person-packages.txt b/lib/lp/soyuz/stories/soyuz/xx-person-packages.txt
3478index 91de3c5..d4e2382 100644
3479--- a/lib/lp/soyuz/stories/soyuz/xx-person-packages.txt
3480+++ b/lib/lp/soyuz/stories/soyuz/xx-person-packages.txt
3481@@ -417,7 +417,7 @@ Please note also that disabled archives are not viewable by anonymous users.
3482 >>> def print_archive_package_rows(contents):
3483 ... package_table = find_tag_by_id(
3484 ... anon_browser.contents, 'packages_list')
3485- ... for ppa_row in package_table.findChildren('tr'):
3486+ ... for ppa_row in package_table.find_all('tr'):
3487 ... print(extract_text(ppa_row))
3488
3489 >>> anon_browser.open("http://launchpad.test/~cprov/+archive/ppa")
3490diff --git a/lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt b/lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt
3491index 3a93c4d..00d8cca 100644
3492--- a/lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt
3493+++ b/lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt
3494@@ -217,7 +217,7 @@ The 'filelist' is expanded as one or more table rows, right below the
3495 clicked item:
3496
3497 >>> filelist_body = first_tag_by_class(anon_browser.contents, 'queue-4')
3498- >>> filelist = filelist_body.findAll('tr')
3499+ >>> filelist = filelist_body.find_all('tr')
3500
3501 It contains a list of files related to the queue item clicked, followed
3502 by its size, one file per line. Expired files have no size.
3503diff --git a/lib/lp/testing/matchers.py b/lib/lp/testing/matchers.py
3504index 5b14a38..1f36696 100644
3505--- a/lib/lp/testing/matchers.py
3506+++ b/lib/lp/testing/matchers.py
3507@@ -432,7 +432,7 @@ class MatchesTagText(Matcher):
3508 def match(self, matchee):
3509 # Here to avoid circular dependancies.
3510 from lp.testing.pages import extract_text
3511- widgets = self.soup_content.findAll(id=self.tag_id)
3512+ widgets = self.soup_content.find_all(id=self.tag_id)
3513 if len(widgets) == 0:
3514 return MissingElement(self.tag_id, self.soup_content)
3515 elif len(widgets) > 1:
3516@@ -456,13 +456,13 @@ class MatchesPickerText(Matcher):
3517 def match(self, matchee):
3518 # Here to avoid circular dependancies.
3519 from lp.testing.pages import extract_text
3520- widgets = self.soup_content.findAll(id=self.widget_id)
3521+ widgets = self.soup_content.find_all(id=self.widget_id)
3522 if len(widgets) == 0:
3523 return MissingElement(self.widget_id, self.soup_content)
3524 elif len(widgets) > 1:
3525 return MultipleElements(self.widget_id, self.soup_content)
3526 widget = widgets[0]
3527- text = widget.findAll(attrs={'class': 'yui3-activator-data-box'})[0]
3528+ text = widget.find_all(attrs={'class': 'yui3-activator-data-box'})[0]
3529 text_matcher = DocTestMatches(extract_text(text))
3530 return text_matcher.match(matchee)
3531
3532diff --git a/lib/lp/testing/pages.py b/lib/lp/testing/pages.py
3533index 8e54faa..35a6f10 100644
3534--- a/lib/lp/testing/pages.py
3535+++ b/lib/lp/testing/pages.py
3536@@ -229,7 +229,7 @@ def find_tags_by_class(content, class_, only_first=False):
3537 if only_first:
3538 find = BeautifulSoup.find
3539 else:
3540- find = BeautifulSoup.findAll
3541+ find = BeautifulSoup.find_all
3542 return find(soup, attrs={'class': class_matcher})
3543
3544
3545@@ -289,11 +289,11 @@ def print_table(content, columns=None, skip_rows=None, sep="\t"):
3546 None no rows are skipped.
3547 :param sep the separator to be used between output items.
3548 """
3549- for row_num, row in enumerate(content.findAll('tr')):
3550+ for row_num, row in enumerate(content.find_all('tr')):
3551 if skip_rows is not None and row_num in skip_rows:
3552 continue
3553 row_content = []
3554- for col_num, item in enumerate(row.findAll('td')):
3555+ for col_num, item in enumerate(row.find_all('td')):
3556 if columns is None or col_num in columns:
3557 row_content.append(extract_text(item))
3558 if len(row_content) > 0:
3559@@ -306,7 +306,7 @@ def get_radio_button_text_for_field(soup, name):
3560 The resulting output will look something like:
3561 ['(*) A checked option', '( ) An unchecked option']
3562 """
3563- buttons = soup.findAll(
3564+ buttons = soup.find_all(
3565 'input', {'name': 'field.%s' % name})
3566 for button in buttons:
3567 if button.parent.name == 'label':
3568@@ -444,7 +444,7 @@ def parse_relationship_section(content):
3569 if section is None:
3570 print('EMPTY SECTION')
3571 return
3572- for li in section.findAll('li'):
3573+ for li in section.find_all('li'):
3574 if li.a:
3575 link = li.a
3576 content = whitespace_re.sub(' ', link.string.strip())
3577@@ -461,7 +461,7 @@ def print_action_links(content):
3578 if actions is None:
3579 print("No actions portlet")
3580 return
3581- entries = actions.findAll('li')
3582+ entries = actions.find_all('li')
3583 for entry in entries:
3584 if entry.a:
3585 print('%s: %s' % (entry.a.string, entry.a['href']))
3586@@ -478,7 +478,7 @@ def print_navigation_links(content):
3587 title = navigation_links.find('label')
3588 if title is not None:
3589 print('= %s =' % title.string)
3590- entries = navigation_links.findAll(['strong', 'a'])
3591+ entries = navigation_links.find_all(['strong', 'a'])
3592 for entry in entries:
3593 try:
3594 print('%s: %s' % (entry.span.string, entry['href']))
3595@@ -506,7 +506,7 @@ def print_portlet_links(content, name, base=None):
3596 if portlet_contents is None:
3597 print("No portlet found with name:", name)
3598 return
3599- portlet_links = portlet_contents.findAll('a')
3600+ portlet_links = portlet_contents.find_all('a')
3601 if len(portlet_links) == 0:
3602 print("No links were found in the portlet.")
3603 return
3604@@ -520,7 +520,7 @@ def print_submit_buttons(content):
3605
3606 Use this to check that the buttons on a page match your expectations.
3607 """
3608- buttons = find_main_content(content).findAll(
3609+ buttons = find_main_content(content).find_all(
3610 'input', attrs={'class': 'button', 'type': 'submit'})
3611 if buttons is None:
3612 print("No buttons found")
3613@@ -571,9 +571,9 @@ def print_location(contents):
3614 The main heading is the first <h1> element in the page.
3615 """
3616 doc = find_tag_by_id(contents, 'document')
3617- heading = doc.find(attrs={'id': 'watermark-heading'}).findAll('a')
3618+ heading = doc.find(attrs={'id': 'watermark-heading'}).find_all('a')
3619 container = doc.find(attrs={'class': 'breadcrumbs'})
3620- hierarchy = container.findAll(recursive=False) if container else []
3621+ hierarchy = container.find_all(recursive=False) if container else []
3622 segments = [extract_text(step) for step in chain(heading, hierarchy)]
3623
3624 if len(segments) == 0:
3625@@ -598,9 +598,9 @@ def print_location_apps(contents):
3626 if location_apps is None:
3627 location_apps = first_tag_by_class(contents, 'watermark-apps-portlet')
3628 if location_apps is not None:
3629- location_apps = location_apps.ul.findAll('li')
3630+ location_apps = location_apps.ul.find_all('li')
3631 else:
3632- location_apps = location_apps.findAll('span')
3633+ location_apps = location_apps.find_all('span')
3634 if location_apps is None:
3635 print("(Application tabs omitted)")
3636 elif len(location_apps) == 0:
3637diff --git a/lib/lp/translations/stories/distribution/xx-distribution-translations.txt b/lib/lp/translations/stories/distribution/xx-distribution-translations.txt
3638index 5eb3ffa..01d5dde 100644
3639--- a/lib/lp/translations/stories/distribution/xx-distribution-translations.txt
3640+++ b/lib/lp/translations/stories/distribution/xx-distribution-translations.txt
3641@@ -58,7 +58,7 @@ to the right translation focus.
3642 And the other Ubuntu distributions should be there too.
3643
3644 >>> content = find_main_content(browser.contents)
3645- >>> print(extract_text(content.findAll('h2')[1]))
3646+ >>> print(extract_text(content.find_all('h2')[1]))
3647 Other versions of Ubuntu
3648
3649 >>> print(extract_text(content.find(id='distroseries-list')))
3650@@ -112,7 +112,7 @@ languages pointing to the latest release, Hoary.
3651 And the other Ubuntu distributions should be there too.
3652
3653 >>> content = find_main_content(browser.contents)
3654- >>> print(extract_text(content.findAll('h2')[1]))
3655+ >>> print(extract_text(content.find_all('h2')[1]))
3656 Other versions of Debian
3657
3658 >>> print(extract_text(content.find(id='distroseries-list')))
3659diff --git a/lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt b/lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt
3660index bb3e509..f56e903 100644
3661--- a/lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt
3662+++ b/lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt
3663@@ -90,7 +90,7 @@ the system tells them that they're not allowed to see those pages.
3664 ...
3665 urllib.error.HTTPError: HTTP Error 503: Service Unavailable
3666 >>> main_content = find_main_content(user_browser.contents)
3667- >>> print(main_content.findNext('p').decode_contents())
3668+ >>> print(main_content.find_next('p').decode_contents())
3669 Translations for this release series are not available yet.
3670
3671 >>> user_browser.handleErrors = False
3672diff --git a/lib/lp/translations/stories/importqueue/xx-translation-import-queue-filtering.txt b/lib/lp/translations/stories/importqueue/xx-translation-import-queue-filtering.txt
3673index 2f20ce5..63c2dc1 100644
3674--- a/lib/lp/translations/stories/importqueue/xx-translation-import-queue-filtering.txt
3675+++ b/lib/lp/translations/stories/importqueue/xx-translation-import-queue-filtering.txt
3676@@ -311,7 +311,7 @@ The only entry that shows up now is the one Carlos just uploaded.
3677
3678 >>> import_list = find_tag_by_id(
3679 ... user_browser.contents, 'import-entries-list')
3680- >>> first_entry = import_list.findNext('tr')
3681+ >>> first_entry = import_list.find_next('tr')
3682 >>> print(represent_queue_entry(first_entry))
3683 foo.pot in evolution in Ubuntu Hoary
3684 Needs Review
3685@@ -332,7 +332,7 @@ Ubuntu.
3686 ... output = []
3687 ... import_list = find_tag_by_id(
3688 ... browser.contents, 'import-entries-list')
3689- ... for entry in import_list.findAll('tr'):
3690+ ... for entry in import_list.find_all('tr'):
3691 ... output.append(represent_queue_entry(entry))
3692 ... return '\n'.join(output)
3693
3694diff --git a/lib/lp/translations/stories/importqueue/xx-translation-import-queue-targets.txt b/lib/lp/translations/stories/importqueue/xx-translation-import-queue-targets.txt
3695index 6efe24a..6f1a12d 100644
3696--- a/lib/lp/translations/stories/importqueue/xx-translation-import-queue-targets.txt
3697+++ b/lib/lp/translations/stories/importqueue/xx-translation-import-queue-targets.txt
3698@@ -66,13 +66,13 @@ There are two entries in the list.
3699
3700 >>> import_list = find_tag_by_id(
3701 ... user_browser.contents, 'import-entries-list')
3702- >>> first_entry = import_list.findNext('tr')
3703+ >>> first_entry = import_list.find_next('tr')
3704 >>> print(extract_text(first_entry))
3705 po/evolution-2.2-test.pot in
3706 Evolution trunk series
3707 Imported
3708- >>> second_entry = first_entry.findNext(
3709- ... 'tr').findNext('tr').findNext('tr')
3710+ >>> second_entry = first_entry.find_next(
3711+ ... 'tr').find_next('tr').find_next('tr')
3712 >>> print(extract_text(second_entry))
3713 po/pt_BR.po in
3714 Evolution trunk series
3715@@ -100,13 +100,13 @@ Evolution product are for this trunk series.
3716
3717 >>> import_list = find_tag_by_id(
3718 ... user_browser.contents, 'import-entries-list')
3719- >>> first_entry = import_list.findNext('tr')
3720+ >>> first_entry = import_list.find_next('tr')
3721 >>> print(extract_text(first_entry))
3722 po/evolution-2.2-test.pot in
3723 Evolution trunk series
3724 Imported
3725- >>> second_entry = first_entry.findNext(
3726- ... 'tr').findNext('tr').findNext('tr')
3727+ >>> second_entry = first_entry.find_next(
3728+ ... 'tr').find_next('tr').find_next('tr')
3729 >>> print(extract_text(second_entry))
3730 po/pt_BR.po in
3731 Evolution trunk series
3732@@ -134,23 +134,22 @@ it here too.
3733
3734 >>> import_list = find_tag_by_id(
3735 ... user_browser.contents, 'import-entries-list')
3736- >>> first_entry = import_list.findNext('tr')
3737+ >>> first_entry = import_list.find_next('tr')
3738 >>> print(extract_text(first_entry))
3739 po/evolution-2.2-test.pot in
3740 Evolution trunk series
3741 Imported
3742- >>> first_entry_importer = first_entry.findNext('tr')
3743+ >>> first_entry_importer = first_entry.find_next('tr')
3744 >>> print(extract_text(first_entry_importer))
3745 Uploaded by
3746 Foo Bar
3747 on 2006-12-13 22:17:56 CET
3748- >>> second_entry = first_entry_importer.findNext(
3749- ... 'tr').findNext('tr')
3750+ >>> second_entry = first_entry_importer.find_next('tr').find_next('tr')
3751 >>> print(extract_text(second_entry))
3752 po/pt_BR.po in
3753 Evolution trunk series
3754 Imported
3755- >>> second_entry_importer = second_entry.findNext('tr')
3756+ >>> second_entry_importer = second_entry.find_next('tr')
3757 >>> print(extract_text(second_entry_importer))
3758 Uploaded by
3759 Foo Bar
3760diff --git a/lib/lp/translations/stories/productseries/xx-productseries-translations.txt b/lib/lp/translations/stories/productseries/xx-productseries-translations.txt
3761index c649f0b..b2b562c 100644
3762--- a/lib/lp/translations/stories/productseries/xx-productseries-translations.txt
3763+++ b/lib/lp/translations/stories/productseries/xx-productseries-translations.txt
3764@@ -33,7 +33,7 @@ Listing languages with translations is best checked with a helper method.
3765 ... print("%-25s %13s %13s" % (
3766 ... "Language", "Untranslated", "Unreviewed"))
3767 ... for row in language_rows:
3768- ... cols = row.findAll('td')
3769+ ... cols = row.find_all('td')
3770 ... language = extract_text(cols[0])
3771 ... untranslated = extract_link_info(cols[2])
3772 ... unreviewed = extract_link_info(cols[3])
3773@@ -50,7 +50,7 @@ being set up for translation.
3774 Series trunk : Translations : Frobnicator
3775
3776 >>> main_content = find_main_content(anon_browser.contents)
3777- >>> print(extract_text(main_content.findAll('h1')[0]))
3778+ >>> print(extract_text(main_content.find_all('h1')[0]))
3779 Translation status by language
3780
3781 >>> print_language_stats(anon_browser)
3782@@ -59,7 +59,7 @@ being set up for translation.
3783 Explanation is shown to indicate that there are no translations for
3784 this series.
3785
3786- >>> print(extract_text(main_content.findAll('p')[0]))
3787+ >>> print(extract_text(main_content.find_all('p')[0]))
3788 There are no translations for this release series.
3789
3790 Administrator will also see instructions on how to set up a project for
3791@@ -67,8 +67,8 @@ translation.
3792
3793 >>> admin_browser.open(frobnicator_trunk_url)
3794 >>> main_content = find_main_content(admin_browser.contents)
3795- >>> paragraphs = main_content.findAll('p')
3796- >>> print(extract_text(main_content.findAll('p')[1]))
3797+ >>> paragraphs = main_content.find_all('p')
3798+ >>> print(extract_text(main_content.find_all('p')[1]))
3799 To start translating your project...
3800
3801 With one translatable template (with fake stats for 10 messages), a listing
3802diff --git a/lib/lp/translations/stories/standalone/xx-licensing.txt b/lib/lp/translations/stories/standalone/xx-licensing.txt
3803index 669f49c..5f2ef92 100644
3804--- a/lib/lp/translations/stories/standalone/xx-licensing.txt
3805+++ b/lib/lp/translations/stories/standalone/xx-licensing.txt
3806@@ -49,10 +49,10 @@ nor input boxes available.
3807
3808 >>> main_content = find_tag_by_id(
3809 ... browser.contents, 'messages_to_translate')
3810- >>> for textarea in main_content.findAll('textarea'):
3811+ >>> for textarea in main_content.find_all('textarea'):
3812 ... print('Found textarea:\n%s' % textarea)
3813
3814- >>> for input in main_content.findAll('input'):
3815+ >>> for input in main_content.find_all('input'):
3816 ... print('Found input:\n%s' % input)
3817
3818 Karl changes his mind. He returns to the licensing page.
3819diff --git a/lib/lp/translations/stories/standalone/xx-person-activity.txt b/lib/lp/translations/stories/standalone/xx-person-activity.txt
3820index 3e8640e..7b34e96 100644
3821--- a/lib/lp/translations/stories/standalone/xx-person-activity.txt
3822+++ b/lib/lp/translations/stories/standalone/xx-person-activity.txt
3823@@ -21,7 +21,7 @@ listed which Carlos has contributed to.
3824
3825 # Prints a heading and formatted list of POFiles and latest submissions.
3826 >>> def print_activity_list(listing):
3827- ... for row in listing.findAll('tr'):
3828+ ... for row in listing.find_all('tr'):
3829 ... print(extract_text(row))
3830
3831 >>> listing = find_tag_by_id(anon_browser.contents, 'activity-table')
3832diff --git a/lib/lp/translations/stories/standalone/xx-pofile-details.txt b/lib/lp/translations/stories/standalone/xx-pofile-details.txt
3833index 8efea71..a54e2a7 100644
3834--- a/lib/lp/translations/stories/standalone/xx-pofile-details.txt
3835+++ b/lib/lp/translations/stories/standalone/xx-pofile-details.txt
3836@@ -52,9 +52,9 @@ a separate method to pretty-print all the translations.
3837 ... return ' '.join(contents)
3838 ...
3839 ... table = find_tags_by_class(browser.contents, 'listing')[0]
3840- ... rows = table.findAll('tr')
3841+ ... rows = table.find_all('tr')
3842 ... for row in rows:
3843- ... cells = row.findAll('td')
3844+ ... cells = row.find_all('td')
3845 ... type = get_first_defined_class(cells)
3846 ... types = { 'englishstring' : 'english',
3847 ... 'usedtranslation' : ' used',
3848diff --git a/lib/lp/translations/stories/standalone/xx-pofile-export.txt b/lib/lp/translations/stories/standalone/xx-pofile-export.txt
3849index 364c90d..30c77c3 100644
3850--- a/lib/lp/translations/stories/standalone/xx-pofile-export.txt
3851+++ b/lib/lp/translations/stories/standalone/xx-pofile-export.txt
3852@@ -87,7 +87,7 @@ evolution yet; it will be created at the moment the export is requested.
3853 ... browser.contents, 'Translation file details')
3854 >>> carlos = u'Carlos Perell\xf3 Mar\xedn'
3855 >>> creator = extract_text(
3856- ... translation_portlet.find(text='Creator:').findNext('a'))
3857+ ... translation_portlet.find(text='Creator:').find_next('a'))
3858 >>> carlos in creator
3859 True
3860
3861diff --git a/lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt b/lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt
3862index f4ce694..35d5b00 100644
3863--- a/lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt
3864+++ b/lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt
3865@@ -24,7 +24,7 @@ messages in the batches of 10 items.
3866 ...
3867 ... if soup is None:
3868 ... soup = find_main_content(browser.contents)
3869- ... for tag in soup.findAll('label'):
3870+ ... for tag in soup.find_all('label'):
3871 ... id = tag.get('id')
3872 ... if id is not None:
3873 ... match = re.match(match_translation_id, id)
3874diff --git a/lib/lp/translations/stories/standalone/xx-pofile-translate-newlines-check.txt b/lib/lp/translations/stories/standalone/xx-pofile-translate-newlines-check.txt
3875index d0f8190..4ddbbe3 100644
3876--- a/lib/lp/translations/stories/standalone/xx-pofile-translate-newlines-check.txt
3877+++ b/lib/lp/translations/stories/standalone/xx-pofile-translate-newlines-check.txt
3878@@ -11,7 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=299009
3879 >>> def print_tags(browser, tags):
3880 ... """Find and print [tags] in browser.contents. End each with '--'."""
3881 ... soup = find_main_content(browser.contents)
3882- ... for tag in soup.findAll(attrs={'id': tags}):
3883+ ... for tag in soup.find_all(attrs={'id': tags}):
3884 ... print(u"%s\n--\n" % tag.decode_contents())
3885
3886 >>> browser = setupBrowser(auth='Basic carlos@canonical.com:test')
3887diff --git a/lib/lp/translations/stories/standalone/xx-pofile-translate.txt b/lib/lp/translations/stories/standalone/xx-pofile-translate.txt
3888index 2d8e3a9..21f81b8 100644
3889--- a/lib/lp/translations/stories/standalone/xx-pofile-translate.txt
3890+++ b/lib/lp/translations/stories/standalone/xx-pofile-translate.txt
3891@@ -38,12 +38,12 @@ The page is rendered in read-only mode, without any textareas for input.
3892
3893 >>> main_content = find_tag_by_id(
3894 ... browser.contents, 'messages_to_translate')
3895- >>> for textarea in main_content.findAll('textarea'):
3896+ >>> for textarea in main_content.find_all('textarea'):
3897 ... print('Found textarea:\n%s' % textarea)
3898
3899 In fact, no input widgets at all are displayed.
3900
3901- >>> for input in main_content.findAll('input'):
3902+ >>> for input in main_content.find_all('input'):
3903 ... print('Found input:\n%s' % input)
3904
3905 As an anynoymous user you will have access to the download and details
3906@@ -139,7 +139,7 @@ they must adhere religiously to an agreed-to format.
3907 ... content = find_main_content(browser.contents)
3908 ... ids = [
3909 ... tag.get(attribute)
3910- ... for tag in content.findAll()
3911+ ... for tag in content.find_all()
3912 ... if re.match(prefix, tag.get(attribute,''))]
3913 ... return sorted(ids)
3914
3915diff --git a/lib/lp/translations/stories/standalone/xx-potemplate-index.txt b/lib/lp/translations/stories/standalone/xx-potemplate-index.txt
3916index a471655..8b1a394 100644
3917--- a/lib/lp/translations/stories/standalone/xx-potemplate-index.txt
3918+++ b/lib/lp/translations/stories/standalone/xx-potemplate-index.txt
3919@@ -35,11 +35,11 @@ show the number of messages that are untranslated, the percentage
3920 that represents, when the translation was updated, and by whom.
3921
3922 >>> content = find_main_content(anon_browser.contents)
3923- >>> print(extract_text(content.findAll('h1')[0]))
3924+ >>> print(extract_text(content.find_all('h1')[0]))
3925 Translation status
3926
3927- >>> table = content.findAll('table')[0]
3928- >>> for row in table.findAll('tr'):
3929+ >>> table = content.find_all('table')[0]
3930+ >>> for row in table.find_all('tr'):
3931 ... print(extract_text(row, formatter='html'))
3932 Language Status Untranslated Need review Changed Last Edited By
3933 Afrikaans 22 ... ... &mdash; &mdash;
3934@@ -58,7 +58,7 @@ English translations, but they are not displayed to the user.
3935 >>> anon_browser.open('http://translations.launchpad.test/ubuntu/hoary/'
3936 ... '+source/mozilla/+pots/pkgconf-mozilla')
3937 >>> table = find_tag_by_id(anon_browser.contents, 'language-chart')
3938- >>> for row in table.findAll('tr')[0:6]:
3939+ >>> for row in table.find_all('tr')[0:6]:
3940 ... print(extract_text(row, formatter='html'))
3941 Language Status Untranslated Need review Changed Last Edited By
3942 Afrikaans 9 ... ... ... &mdash;
3943diff --git a/lib/lp/translations/stories/standalone/xx-product-translations.txt b/lib/lp/translations/stories/standalone/xx-product-translations.txt
3944index 6ae0603..2850738 100644
3945--- a/lib/lp/translations/stories/standalone/xx-product-translations.txt
3946+++ b/lib/lp/translations/stories/standalone/xx-product-translations.txt
3947@@ -21,7 +21,7 @@ A helper method to print out language chart.
3948 ... print("%-25s %13s %13s" % (
3949 ... "Language", "Untranslated", "Unreviewed"))
3950 ... for row in language_rows:
3951- ... cols = row.findAll('td')
3952+ ... cols = row.find_all('td')
3953 ... language = extract_text(cols[0])
3954 ... untranslated = extract_text(cols[2])
3955 ... unreviewed = extract_text(cols[3])
3956diff --git a/lib/lp/translations/stories/standalone/xx-rosetta-distributionsourcepackage-list.txt b/lib/lp/translations/stories/standalone/xx-rosetta-distributionsourcepackage-list.txt
3957index 732f11a..2139631 100644
3958--- a/lib/lp/translations/stories/standalone/xx-rosetta-distributionsourcepackage-list.txt
3959+++ b/lib/lp/translations/stories/standalone/xx-rosetta-distributionsourcepackage-list.txt
3960@@ -18,7 +18,7 @@ This page directs users to SourcePackage translations pages.
3961
3962 The focus' two templates are shown.
3963
3964- >>> template_names = content.findAll('h2')
3965+ >>> template_names = content.find_all('h2')
3966 >>> for name in template_names:
3967 ... print(extract_text(name))
3968 Template "evolution-2.2" in Ubuntu Hoary package "evolution"
3969@@ -27,7 +27,7 @@ The focus' two templates are shown.
3970
3971 Other series are also listed.
3972
3973- >>> for other in content.find(id='distroseries-list').findAll('li'):
3974+ >>> for other in content.find(id='distroseries-list').find_all('li'):
3975 ... print(extract_text(other))
3976 Breezy Badger Autotest (6.6.6)
3977 Grumpy (5.10)
3978diff --git a/lib/lp/translations/stories/standalone/xx-rosetta-homepage.txt b/lib/lp/translations/stories/standalone/xx-rosetta-homepage.txt
3979index 7e940c7..238ba73 100644
3980--- a/lib/lp/translations/stories/standalone/xx-rosetta-homepage.txt
3981+++ b/lib/lp/translations/stories/standalone/xx-rosetta-homepage.txt
3982@@ -40,13 +40,13 @@ translated projects.
3983
3984 >>> middle_column = find_tags_by_class(
3985 ... browser.contents, 'three column middle')[0]
3986- >>> heading = middle_column.findAll('h2')[0]
3987+ >>> heading = middle_column.find_all('h2')[0]
3988 >>> print(extract_text(heading))
3989 Translatable projects
3990- >>> for project in middle_column.findAll('span'):
3991+ >>> for project in middle_column.find_all('span'):
3992 ... print(extract_text(project))
3993 Evolution
3994- >>> print(extract_text(middle_column.findAll('div')[0]))
3995+ >>> print(extract_text(middle_column.find_all('div')[0]))
3996 » List all translatable projects...
3997
3998 The translation front page list of the user's translatable languages.
3999@@ -63,5 +63,5 @@ in the right column.
4000 ...
4001 Change your preferred languages...
4002
4003- >>> right_column.findAll('a')[-1]
4004+ >>> right_column.find_all('a')[-1]
4005 <a href="/+editmylanguages"...Change your preferred languages...
4006diff --git a/lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt b/lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt
4007index cae0b43..74c35dc 100644
4008--- a/lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt
4009+++ b/lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt
4010@@ -16,12 +16,12 @@ IP address, since we'll use that later.
4011 'Hoary (5.04) : Translations : ...evolution...package : Ubuntu'
4012
4013 >>> content = find_main_content(anon_browser.contents)
4014- >>> print(backslashreplace(extract_text(content.findAll('h1')[0])))
4015+ >>> print(backslashreplace(extract_text(content.find_all('h1')[0])))
4016 Translations for evolution in Ubuntu Hoary
4017
4018 There are two templates for evolution in Ubuntu Hoary
4019
4020- >>> template_names = content.findAll('h2')
4021+ >>> template_names = content.find_all('h2')
4022 >>> for name in template_names:
4023 ... print(extract_text(name))
4024 Template "evolution-2.2" in Ubuntu Hoary package "evolution"
4025@@ -34,8 +34,8 @@ comprised of the translated languages plus the languages of the user,
4026 100% of the strings are untranslated. The Last and Edited By columns
4027 indicate that these languages have never been edited my anyone.
4028
4029- >>> table = content.findAll('table')[0]
4030- >>> for row in table.findAll('tr'):
4031+ >>> table = content.find_all('table')[0]
4032+ >>> for row in table.find_all('tr'):
4033 ... print(extract_text(row, formatter='html'))
4034 Language Status Untranslated Need review Changed Last Edited By
4035 Afrikaans 22 ... ... &mdash; &mdash;
4036diff --git a/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt b/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt
4037index ef3da1c..2c8bf6b 100644
4038--- a/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt
4039+++ b/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt
4040@@ -29,12 +29,12 @@ We are in read only mode, so there shouldn't be any textareas:
4041
4042 >>> main_content = find_tag_by_id(
4043 ... browser.contents, 'messages_to_translate')
4044- >>> for textarea in main_content.findAll('textarea'):
4045+ >>> for textarea in main_content.find_all('textarea'):
4046 ... raise AssertionError('Found textarea:\n%s' % textarea)
4047
4048 Neither any input widget:
4049
4050- >>> for input in main_content.findAll('input'):
4051+ >>> for input in main_content.find_all('input'):
4052 ... raise AssertionError('Found input:\n%s' % input)
4053
4054 As an anynoymous user you will have access to the download and details
4055@@ -463,7 +463,7 @@ Also, we should still have previous translation:
4056 But also, the new one should appear in the form.
4057
4058 >>> import re
4059- >>> elements = find_main_content(slow_submission.contents).findAll(
4060+ >>> elements = find_main_content(slow_submission.contents).find_all(
4061 ... True, {'id': re.compile(r'^msgset_143_es_suggestion_\d+_0$')})
4062 >>> for element in elements:
4063 ... print(element.decode_contents())
4064diff --git a/lib/lp/translations/stories/standalone/xx-translations-to-review.txt b/lib/lp/translations/stories/standalone/xx-translations-to-review.txt
4065index c90ebbe..69bc89a 100644
4066--- a/lib/lp/translations/stories/standalone/xx-translations-to-review.txt
4067+++ b/lib/lp/translations/stories/standalone/xx-translations-to-review.txt
4068@@ -54,8 +54,8 @@ Xowxz is a Khmer reviewer.
4069 ... listing = soup.find(id="translations-to-review-table")
4070 ... if listing:
4071 ... count = 0
4072- ... for tr in listing.findAll('tr'):
4073- ... tds = [td.decode_contents() for td in tr.findAll('td')]
4074+ ... for tr in listing.find_all('tr'):
4075+ ... tds = [td.decode_contents() for td in tr.find_all('td')]
4076 ... print(' '.join(tds))
4077 ... count += 1
4078 ... print("Listing contains %d translation(s)." % count)
4079diff --git a/lib/lp/translations/stories/translationgroups/xx-link-to-documentation.txt b/lib/lp/translations/stories/translationgroups/xx-link-to-documentation.txt
4080index 09c4504..bd2b3db 100644
4081--- a/lib/lp/translations/stories/translationgroups/xx-link-to-documentation.txt
4082+++ b/lib/lp/translations/stories/translationgroups/xx-link-to-documentation.txt
4083@@ -31,11 +31,11 @@ This way he can also set the documentation URL.
4084 The link now appears in the table next to the name of the team.
4085
4086 >>> team = first_tag_by_class(carlos_browser.contents, 'translator-team')
4087- >>> print(extract_text(team.findAll('a')[0]))
4088+ >>> print(extract_text(team.find_all('a')[0]))
4089 testing Spanish team
4090
4091 >>> link = first_tag_by_class(carlos_browser.contents, 'translator-link')
4092- >>> print(link.findAll('a')[0]['href'])
4093+ >>> print(link.find_all('a')[0]['href'])
4094 http://www.ubuntu.com/
4095
4096 Back on the translations page, the link is now present, too.
4097@@ -148,7 +148,7 @@ to said documentation.
4098 Before translating, be sure to go through Just a testing team
4099 instructions.
4100
4101- >>> links = notification.findAll('a')
4102+ >>> links = notification.find_all('a')
4103 >>> print(links[0]['href'])
4104 https://help.launchpad.net/
4105
4106@@ -161,7 +161,7 @@ Adding the Spanish team documentation URL adds another link.
4107 Before translating, be sure to go through Just a testing team
4108 instructions and Spanish guidelines.
4109
4110- >>> links = notification.findAll('a')
4111+ >>> links = notification.find_all('a')
4112 >>> print(links[0]['href'])
4113 https://help.launchpad.net/
4114 >>> print(links[1]['href'])
4115@@ -177,6 +177,6 @@ the narrative is changed a bit to include the full team name.
4116 Before translating, be sure to go through testing Spanish team
4117 guidelines.
4118
4119- >>> links = notification.findAll('a')
4120+ >>> links = notification.find_all('a')
4121 >>> print(links[0]['href'])
4122 https://help.launchpad.net/Spanish
4123diff --git a/lib/lp/translations/stories/translationgroups/xx-translationgroups.txt b/lib/lp/translations/stories/translationgroups/xx-translationgroups.txt
4124index 4d8effc..96ebe8f 100644
4125--- a/lib/lp/translations/stories/translationgroups/xx-translationgroups.txt
4126+++ b/lib/lp/translations/stories/translationgroups/xx-translationgroups.txt
4127@@ -168,9 +168,9 @@ The new groups should show up on the "Translation groups" page.
4128
4129 >>> groups_table = find_tag_by_id(
4130 ... anon_browser.contents, 'translation-groups')
4131- >>> groups = groups_table.find('tbody').findAll('tr')
4132+ >>> groups = groups_table.find('tbody').find_all('tr')
4133 >>> for group_row in groups:
4134- ... group = group_row.findNext('td')
4135+ ... group = group_row.find_next('td')
4136 ... print('%s: %s' % (group.a.string, group.a['href']))
4137 Just a testing team: ...testing-translation-team
4138 Single-language Translators: ...monolingua
4139@@ -461,7 +461,7 @@ group has been assigned as the translator for.
4140 ... return find_tag_by_id(browser.contents, "related-projects")
4141
4142 >>> portlet = find_projects_portlet(browser)
4143- >>> for link in portlet.findAll('a'):
4144+ >>> for link in portlet.find_all('a'):
4145 ... print('%s: %s' % (link.find(text=True), link['href']))
4146 Ubuntu: http://launchpad.test/ubuntu
4147 GNOME: http://launchpad.test/gnome
4148@@ -496,7 +496,7 @@ They disappear from the listing:
4149 http://translations.launchpad.test/+groups/polyglot
4150
4151 >>> portlet = find_projects_portlet(browser)
4152- >>> for link in portlet.findAll('a'):
4153+ >>> for link in portlet.find_all('a'):
4154 ... print('%s: %s' % (link.string, link['href']))
4155 Ubuntu: http://launchpad.test/ubuntu
4156
4157@@ -645,11 +645,11 @@ The system allows us to change the translator for a concrete language
4158
4159 >>> portlet = find_tag_by_id(
4160 ... anon_browser.contents, "translation-teams-listing")
4161- >>> language_rows = portlet.find('tbody').findAll('tr')
4162+ >>> language_rows = portlet.find('tbody').find_all('tr')
4163 >>> for language_row in language_rows:
4164- ... cell = language_row.findNext('td')
4165+ ... cell = language_row.find_next('td')
4166 ... lang_name = extract_text(cell)
4167- ... lang_team = extract_text(cell.findNext('td').findNext('a'))
4168+ ... lang_team = extract_text(cell.find_next('td').find_next('a'))
4169 ... print('%s: %s' % (lang_name, lang_team))
4170 Abkhazian (ab): Hoary Gnome Team
4171 Afrikaans (af): No Privileges Person
4172@@ -717,11 +717,11 @@ instance Welsh (cy), the change will work.
4173
4174 >>> portlet = find_tag_by_id(
4175 ... browser.contents, "translation-teams-listing")
4176- >>> language_rows = portlet.find('tbody').findAll('tr')
4177+ >>> language_rows = portlet.find('tbody').find_all('tr')
4178 >>> for language_row in language_rows:
4179- ... cell = language_row.findNext('td')
4180+ ... cell = language_row.find_next('td')
4181 ... lang_name = extract_text(cell)
4182- ... lang_team = extract_text(cell.findNext('td').findNext('a'))
4183+ ... lang_team = extract_text(cell.find_next('td').find_next('a'))
4184 ... print('%s: %s' % (lang_name, lang_team))
4185 Abkhazian (ab): Hoary Gnome Team
4186 Welsh (cy): No Privileges Person
4187@@ -770,12 +770,12 @@ We are in read only mode, so there shouldn't be any textareas:
4188
4189 >>> main_content = find_tag_by_id(
4190 ... browser.contents, 'messages_to_translate')
4191- >>> for textarea in main_content.findAll('textarea'):
4192+ >>> for textarea in main_content.find_all('textarea'):
4193 ... print('Found textarea:\n%s' % textarea)
4194
4195 Neither any input widget:
4196
4197- >>> for input in main_content.findAll('input'):
4198+ >>> for input in main_content.find_all('input'):
4199 ... print('Found input:\n%s' % input)
4200
4201 However, in Welsh, No Privileges Person does have the ability to edit
4202@@ -1223,7 +1223,7 @@ Let's add a new suggestion as a person without privileges.
4203
4204 Now, we can see the added suggestion + others from the sample data.
4205
4206- >>> for suggestion in find_main_content(browser.contents).findAll(
4207+ >>> for suggestion in find_main_content(browser.contents).find_all(
4208 ... True, {'id': re.compile('msgset_134_es_suggestion_.*')}):
4209 ... print(suggestion)
4210 <...<samp> </samp>new suggestion...
4211diff --git a/lib/lp/translations/stories/translations/xx-translations.txt b/lib/lp/translations/stories/translations/xx-translations.txt
4212index 7c88570..8fb1d3b 100644
4213--- a/lib/lp/translations/stories/translations/xx-translations.txt
4214+++ b/lib/lp/translations/stories/translations/xx-translations.txt
4215@@ -249,7 +249,7 @@ The template title points to the general translate page:
4216 # We are not using browser.getLink because there is no unique way to
4217 # get all of the relevant links, and we don't want to pollute the
4218 # page template with too many IDs useful only for testing.
4219- >>> all_links = evolution_line.findAll('a')
4220+ >>> all_links = evolution_line.find_all('a')
4221 >>> base_href = browser.url
4222 >>> unfiltered = all_links[0]
4223 >>> print(extract_text(unfiltered))
4224@@ -422,7 +422,7 @@ Language title points to the general translate page:
4225 # We are not using browser.getLink because there is no unique way to
4226 # get all of the relevant links, and we don't want to pollute the
4227 # page template with too many IDs useful only for testing.
4228- >>> all_links = spanish_line.findAll('a')
4229+ >>> all_links = spanish_line.find_all('a')
4230 >>> base_href = browser.url
4231 >>> unfiltered = all_links[0]
4232 >>> print(extract_text(unfiltered))
4233diff --git a/utilities/roundup-sniffer.py b/utilities/roundup-sniffer.py
4234index 3035d0e..3d5acf7 100755
4235--- a/utilities/roundup-sniffer.py
4236+++ b/utilities/roundup-sniffer.py
4237@@ -113,7 +113,7 @@ class MplayerStatusSniffer(RoundupSniffer):
4238 soup = BeautifulSoup(page)
4239 return tuple(
4240 node.string for node in
4241- soup.find('th', text='Status').findNext('td').findAll('span'))
4242+ soup.find('th', text='Status').find_next('td').find_all('span'))
4243
4244
4245 def get_distinct(things, fields):

Subscribers

People subscribed via source and target branches

to status/vote changes: