← Back to team overview

launchpad-reviewers team mailing list archive

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

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/beautifulsoup-no-deprecated into lp:launchpad with lp:~cjwatson/launchpad/beautifulsoup-wrapper as a prerequisite.

Commit message:
Stop using pre-3.x BeautifulSoup compatibility methods.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/beautifulsoup-no-deprecated/+merge/332601

These are understandably entirely gone in 4.x.

This is long, but it's totally formulaic and test-only.  .fetch() becomes .findAll() (which unfortunately gets renamed again in 4.x to .find_all(), but at least there's a compatibility method in place), .first() becomes .find(), and .firstText(text) becomes .find(text=text).  The only care needed was to avoid touching non-BeautifulSoup uses of those method names.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/beautifulsoup-no-deprecated into lp:launchpad.
=== modified file 'lib/lp/answers/stories/faq-browse-and-search.txt'
--- lib/lp/answers/stories/faq-browse-and-search.txt	2011-12-23 23:44:59 +0000
+++ lib/lp/answers/stories/faq-browse-and-search.txt	2017-10-23 00:36:01 +0000
@@ -138,7 +138,7 @@
 
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
     >>> for question in questions.findAll('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    ...     print question.find('a').renderContents()
     Installation of Java Runtime Environment for Mozilla
 
 On the question page, there is also a link to consult the FAQs matching

=== modified file 'lib/lp/answers/stories/project-add-question.txt'
--- lib/lp/answers/stories/project-add-question.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/answers/stories/project-add-question.txt	2017-10-23 00:36:01 +0000
@@ -72,7 +72,7 @@
 
     >>> similar_questions = find_tag_by_id(
     ...     user_browser.contents, 'similar-questions')
-    >>> for row in similar_questions.fetch('li'):
+    >>> for row in similar_questions.findAll('li'):
     ...     print row.a.renderContents()
     2: Problem showing the SVG demo on W3C site
 
@@ -93,7 +93,7 @@
 missing:
 
     >>> soup = find_main_content(user_browser.contents)
-    >>> print soup.first('div', 'message').renderContents()
+    >>> print soup.find('div', 'message').renderContents()
     You must enter a summary of your problem.
 
 The product Thunderbird that they selected on the previous screen is still
@@ -112,7 +112,7 @@
 an appropriate message is displayed to inform them of this:
 
     >>> soup = find_main_content(user_browser.contents)
-    >>> print soup.first('p').renderContents()
+    >>> print soup.find('p').renderContents()
     There are no existing FAQs or questions similar to the summary you
     entered.
 
@@ -188,7 +188,7 @@
     >>> user_browser.getControl('Japanese').selected = True
     >>> user_browser.getControl('Save').click()
     >>> soup = find_main_content(user_browser.contents)
-    >>> print soup.first('div', 'informational message').renderContents()
+    >>> print soup.find('div', 'informational message').renderContents()
     Added Japanese to your preferred languages.
 
 So if No Privileges Person were to visit the Ask a Question page for

=== modified file 'lib/lp/answers/stories/question-add-in-other-languages.txt'
--- lib/lp/answers/stories/question-add-in-other-languages.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/answers/stories/question-add-in-other-languages.txt	2017-10-23 00:36:01 +0000
@@ -50,7 +50,7 @@
     already finds nothing.
 
     #>>> for row in similar_questions.findAll('tr', 'noted'):
-    #...     row.first('a').renderContents()
+    #...     row.find('a').renderContents()
     #'Installation of Java Runtime Environment for Mozilla'
     #'Problema al recompilar kernel con soporte smp (doble-n\xc3\xbacleo)'
 

=== modified file 'lib/lp/answers/stories/question-browse-and-search.txt'
--- lib/lp/answers/stories/question-browse-and-search.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/answers/stories/question-browse-and-search.txt	2017-10-23 00:36:01 +0000
@@ -29,7 +29,7 @@
     >>> print browser.title
     Questions : Kubuntu
 
-    >>> print find_main_content(browser.contents).first('p').renderContents()
+    >>> print find_main_content(browser.contents).find('p').renderContents()
     There are no questions for Kubuntu with the requested statuses.
 
 For projects that don't have products, the Answers facet is disabled.
@@ -52,8 +52,8 @@
 He sees a listing of the current questions posted on Ubuntu:
 
     >>> soup = find_main_content(browser.contents)
-    >>> for question in soup.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in soup.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Continue playing after shutdown
     Play DVDs in Totem
     mailto: problem in webpage
@@ -68,8 +68,8 @@
     >>> print browser.title
     Questions : Ubuntu
     >>> soup = find_main_content(browser.contents)
-    >>> for question in soup.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in soup.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Installation failed
 
 This is the last results page, so the next and last links are greyed
@@ -114,11 +114,11 @@
 
     >>> import re
     >>> soup = find_main_content(browser.contents)
-    >>> question_link = soup.first('a', text=re.compile('Play DVDs'))
+    >>> question_link = soup.find('a', text=re.compile('Play DVDs'))
     >>> print question_link.findParent('tr')['title']
     How do you play DVDs in Totem..........?
 
-    >>> question_link = soup.first('a', text=re.compile('Slow system'))
+    >>> question_link = soup.find('a', text=re.compile('Slow system'))
     >>> print question_link.findParent('tr')['title']
     I get really poor hard drive performance.
 
@@ -174,7 +174,7 @@
     >>> print browser.title
     Questions matching "question 8"
 
-    >>> print find_main_content(browser.contents).first('p').renderContents()
+    >>> print find_main_content(browser.contents).find('p').renderContents()
     There are no questions matching "question 8" with the requested statuses.
 
 
@@ -219,8 +219,8 @@
 This time, the search returns one item.
 
     >>> soup = find_main_content(browser.contents)
-    >>> for question in soup.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in soup.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Firefox is slow and consumes too much RAM
 
 He clicks on the link to read the question description.
@@ -294,8 +294,8 @@
     >>> print browser.title
     Questions : Mozilla Firefox
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Firefox loses focus and gets stuck
     Problem showing the SVG demo on W3C site
     Firefox cannot render Bank Site
@@ -314,8 +314,8 @@
     >>> browser.getControl(name='field.search_text').value = 'plugin'
     >>> browser.getControl('Search', index=0).click()
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Problem showing the SVG demo on W3C site
 
 
@@ -334,8 +334,8 @@
     >>> [strip_label(status) for status in statuses]
     ['Answered', 'Solved']
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Play DVDs in Totem
     mailto: problem in webpage
     Installation of Java Runtime Environment for Mozilla
@@ -379,8 +379,8 @@
     'Questions you asked about mozilla-firefox in Ubuntu : Questions : mozilla-firefox package : Ubuntu'
     >>> questions = find_tag_by_id(
     ...     sample_person_browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     mailto: problem in webpage
     Installation of Java Runtime Environment for Mozilla
 
@@ -401,8 +401,8 @@
 
     >>> questions = find_tag_by_id(
     ...     sample_person_browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     mailto: problem in webpage
 
 If the user didn't make any questions on the product, a message
@@ -420,7 +420,7 @@
     ...     'http://launchpad.dev/gnomebaker/+questions')
     >>> sample_person_browser.getLink('My questions').click()
     >>> print find_main_content(
-    ...     sample_person_browser.contents).first('p').renderContents()
+    ...     sample_person_browser.contents).find('p').renderContents()
     You didn't ask any questions about gnomebaker.
 
 
@@ -447,8 +447,8 @@
     Questions needing your attention for Ubuntu : Questions : Ubuntu
     >>> questions = find_tag_by_id(
     ...     sample_person_browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Play DVDs in Totem
     Installation of Java Runtime Environment for Mozilla
 
@@ -472,7 +472,7 @@
     ...    'http://launchpad.dev/products/gnomebaker/+questions')
     >>> sample_person_browser.getLink('Need attention').click()
     >>> print find_main_content(
-    ...     sample_person_browser.contents).first('p').renderContents()
+    ...     sample_person_browser.contents).find('p').renderContents()
     No questions need your attention for gnomebaker.
 
 
@@ -492,8 +492,8 @@
     Questions : Foo Bar
 
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Continue playing after shutdown
     Play DVDs in Totem
     mailto: problem in webpage
@@ -508,8 +508,8 @@
 The listing contains a 'In' column that shows the context where the
 questions was made.
 
-    >>> for question in questions.fetch('td', 'question-target'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'question-target'):
+    ...     print question.find('a').renderContents()
     Ubuntu
     Ubuntu
     mozilla-firefox in Ubuntu
@@ -532,8 +532,8 @@
     ...     'Solved', 'Invalid']
     >>> browser.getControl('Search', index=0).click()
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Firefox is slow and consumes too much RAM
     mailto: problem in webpage
 
@@ -549,7 +549,7 @@
     >>> browser.getLink('Assigned').click()
     >>> print browser.title
     Questions for Foo Bar : Questions : Foo Bar
-    >>> print find_main_content(browser.contents).first('p').renderContents()
+    >>> print find_main_content(browser.contents).find('p').renderContents()
     No questions assigned to Foo Bar found with the requested statuses.
 
 
@@ -562,8 +562,8 @@
     >>> print browser.title
     Questions for Foo Bar : Questions : Foo Bar
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     mailto: problem in webpage
 
 
@@ -576,8 +576,8 @@
     >>> print browser.title
     Questions for Foo Bar : Questions : Foo Bar
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Continue playing after shutdown
     Play DVDs in Totem
     mailto: problem in webpage
@@ -594,8 +594,8 @@
     >>> print browser.title
     Questions for Foo Bar : Questions : Foo Bar
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Slow system
     Firefox loses focus and gets stuck
 
@@ -609,8 +609,8 @@
     >>> print browser.title
     Questions for Foo Bar : Questions : Foo Bar
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Continue playing after shutdown
     Slow system
 
@@ -624,8 +624,8 @@
     >>> print browser.title
     Questions for Foo Bar : Questions : Foo Bar
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Slow system
 
 
@@ -644,11 +644,11 @@
 
     >>> def print_questions_with_target(contents):
     ...     questions = find_tag_by_id(contents, 'question-listing')
-    ...     for question in questions.tbody.fetch('tr'):
-    ...         question_title = question.first(
-    ...             'td', 'questionTITLE').first('a').renderContents()
-    ...         question_target = question.first(
-    ...             'td', 'question-target').first('a').renderContents()
+    ...     for question in questions.tbody.findAll('tr'):
+    ...         question_title = question.find(
+    ...             'td', 'questionTITLE').find('a').renderContents()
+    ...         question_target = question.find(
+    ...             'td', 'question-target').find('a').renderContents()
     ...         print question_title, question_target
     >>> print_questions_with_target(browser.contents)
     Newly installed plug-in doesn't seem to be used Mozilla Firefox
@@ -662,8 +662,8 @@
     >>> browser.getControl('Search', index=0).click()
 
     >>> questions = find_tag_by_id(browser.contents, 'question-listing')
-    >>> for question in questions.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in questions.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Problem showing the SVG demo on W3C site
 
 The same standard reports than on regular QuestionTarget are available:
@@ -724,7 +724,7 @@
     >>> browser.getControl('Search', index=0).click()
 
     >>> print find_main_content(
-    ...     browser.contents).first('p').renderContents()
+    ...     browser.contents).find('p').renderContents()
     There are no questions matching "firefox" with the requested statuses.
 
 Clicking the 'Search' button without entering any search text will

=== modified file 'lib/lp/answers/stories/question-edit.txt'
--- lib/lp/answers/stories/question-edit.txt	2016-08-23 08:05:44 +0000
+++ lib/lp/answers/stories/question-edit.txt	2017-10-23 00:36:01 +0000
@@ -38,11 +38,11 @@
 And viewing that page should show the updated information.
 
     >>> soup = find_main_content(test_browser.contents)
-    >>> print soup.first('div', 'report').renderContents().strip()
+    >>> print soup.find('div', 'report').renderContents().strip()
     <p>Hi! I&#x27;m trying to learn about SVG but I can&#x27;t get it to
     work at all in firefox. Maybe there is a plugin? Help! Thanks.
     Mark</p>
-    >>> print soup.first('h1').renderContents()
+    >>> print soup.find('h1').renderContents()
     Problem showing the SVG demo on W3C web site
 
 You can even modify the title and description of 'Answered' and

=== modified file 'lib/lp/answers/stories/question-overview.txt'
--- lib/lp/answers/stories/question-overview.txt	2014-11-27 22:13:36 +0000
+++ lib/lp/answers/stories/question-overview.txt	2017-10-23 00:36:01 +0000
@@ -32,7 +32,7 @@
     >>> browser.getLink('Answers').click()
 
     >>> soup = find_main_content(browser.contents)
-    >>> print soup.first('h1').renderContents()
+    >>> print soup.find('h1').renderContents()
     Questions for Mozilla Firefox
 
     >>> browser.getLink('Firefox loses focus and gets stuck').url
@@ -61,7 +61,7 @@
     >>> print browser.title
     Question #2 : ...
 
-    >>> print find_main_content(browser.contents).first('h1').renderContents()
+    >>> print find_main_content(browser.contents).find('h1').renderContents()
     Problem showing the SVG demo on W3C site
 
 
@@ -197,7 +197,7 @@
     >>> print browser.title
     Questions : Foo Bar
 
-    >>> print find_main_content(browser.contents).first('h1').renderContents()
+    >>> print find_main_content(browser.contents).find('h1').renderContents()
     Questions for Foo Bar
 
     >>> browser.getLink('Slow system').url

=== modified file 'lib/lp/answers/stories/question-search-multiple-languages.txt'
--- lib/lp/answers/stories/question-search-multiple-languages.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/answers/stories/question-search-multiple-languages.txt	2017-10-23 00:36:01 +0000
@@ -14,8 +14,8 @@
 
     >>> anon_browser.open('http://launchpad.dev/distros/ubuntu/+questions')
     >>> soup = find_main_content(anon_browser.contents)
-    >>> for question in soup.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in soup.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Continue playing after shutdown
     Play DVDs in Totem
     mailto: problem in webpage
@@ -25,8 +25,8 @@
     # Since we have more than 5 results, some of them are in the second batch.
     >>> anon_browser.getLink('Next').click()
     >>> soup = find_main_content(anon_browser.contents)
-    >>> for question in soup.fetch('td', 'questionTITLE'):
-    ...     print question.first('a').renderContents()
+    >>> for question in soup.findAll('td', 'questionTITLE'):
+    ...     print question.find('a').renderContents()
     Installation failed
 
 The questions match the languages inferred from by GeoIP
@@ -46,7 +46,7 @@
     >>> anon_browser.getControl('Search', index=0).click()
     >>> table = find_tag_by_id(anon_browser.contents, 'question-listing')
     >>> for question in table.findAll('td', 'questionTITLE'):
-    ...     question.first('a').renderContents()
+    ...     question.find('a').renderContents()
     'Problema al recompilar kernel con soporte smp (doble-n\xc3\xbacleo)'
     'Continue playing after shutdown'
     'Play DVDs in Totem'
@@ -72,7 +72,7 @@
     >>> anon_browser.getLink('Next').click()
     >>> table = find_tag_by_id(anon_browser.contents, 'question-listing')
     >>> for question in table.findAll('td', 'questionTITLE'):
-    ...     question.first('a').renderContents()
+    ...     question.find('a').renderContents()
     'Slow system'
     'Installation failed'
     '\xd8\xb9\xd9\x83\xd8\xb3 ...
@@ -103,7 +103,7 @@
       ...
     LookupError: name 'field.language...
 
-    >>> content = find_main_content(anon_browser.contents).first('p')
+    >>> content = find_main_content(anon_browser.contents).find('p')
     >>> print content.renderContents()
     There are no questions for Kubuntu with the requested statuses.
 
@@ -132,8 +132,8 @@
     True
 
     >>> soup = find_main_content(anon_browser.contents)
-    >>> for question in soup.fetch('td', 'questionTITLE'):
-    ...     question.first('a').renderContents()
+    >>> for question in soup.findAll('td', 'questionTITLE'):
+    ...     question.find('a').renderContents()
     'Problema al recompilar kernel con soporte smp (doble-n\xc3\xbacleo)'
     'Continue playing after shutdown'
     'Play DVDs in Totem'
@@ -143,8 +143,8 @@
     # Since we have more than 5 results, some of them are in the second batch.
     >>> anon_browser.getLink('Next').click()
     >>> soup = find_main_content(anon_browser.contents)
-    >>> for question in soup.fetch('td', 'questionTITLE'):
-    ...     question.first('a').renderContents()
+    >>> for question in soup.findAll('td', 'questionTITLE'):
+    ...     question.find('a').renderContents()
     'Slow system'
     'Installation failed'
 
@@ -207,8 +207,8 @@
     >>> browser.getControl('English (en)').selected = False
     >>> browser.getControl('Search', index=0).click()
     >>> content = find_main_content(browser.contents)
-    >>> for question in content.fetch('td', 'questionTITLE'):
-    ...     question.first('a').renderContents()
+    >>> for question in content.findAll('td', 'questionTITLE'):
+    ...     question.find('a').renderContents()
     'Problema al recompilar kernel con soporte smp (doble-n\xc3\xbacleo)'
 
 Some users, translators in particular, speak an English variant.
@@ -247,8 +247,8 @@
     >>> daf_browser.getControl('English (en)').selected = True
     >>> daf_browser.getControl('Search', index=0).click()
     >>> content = find_main_content(daf_browser.contents)
-    >>> for question in content.fetch('td', 'questionTITLE'):
-    ...     question.first('a').renderContents()
+    >>> for question in content.findAll('td', 'questionTITLE'):
+    ...     question.find('a').renderContents()
     'Continue playing after shutdown'
     'Play DVDs in Totem'
     'mailto: problem in webpage'
@@ -297,7 +297,7 @@
 
     >>> content = find_main_content(user_browser.contents)
     >>> for question in content.findAll('td', 'questionTITLE'):
-    ...     question.first('a').renderContents()
+    ...     question.find('a').renderContents()
     'Problemas de Impress\xc3\xa3o no Firefox'
 
 The page in all other respects behaves like a question search page.

=== modified file 'lib/lp/answers/stories/question-workflow.txt'
--- lib/lp/answers/stories/question-workflow.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/answers/stories/question-workflow.txt	2017-10-23 00:36:01 +0000
@@ -22,7 +22,7 @@
 
     >>> def  find_last_comment(contents):
     ...     soup = find_main_content(contents)
-    ...     return soup.fetch('div', 'boardCommentBody')[-1]
+    ...     return soup.findAll('div', 'boardCommentBody')[-1]
 
     >>> def print_last_comment(contents):
     ...     print extract_text(find_last_comment(contents))
@@ -86,7 +86,7 @@
 
     >>> support_browser.getControl('Add Information Request').click()
     >>> soup = find_main_content(support_browser.contents)
-    >>> print soup.first('div', 'message').renderContents()
+    >>> print soup.find('div', 'message').renderContents()
     Please enter a message.
 
 
@@ -179,7 +179,7 @@
     >>> owner_browser.open(
     ...     'http://launchpad.dev/firefox/+question/2')
     >>> soup = find_main_content(owner_browser.contents)
-    >>> soup.fetch('div', 'boardComment')[-1].first('input', type='submit')
+    >>> soup.findAll('div', 'boardComment')[-1].find('input', type='submit')
     <input type="submit" name="field.actions.confirm"
      value="This Solved My Problem" />
 
@@ -214,11 +214,11 @@
 The confirmed answer is also highlighted.
 
     >>> soup = find_main_content(owner_browser.contents)
-    >>> bestAnswer = soup.fetch('div', 'boardComment')[-2]
-    >>> print bestAnswer.first('img')
+    >>> bestAnswer = soup.findAll('div', 'boardComment')[-2]
+    >>> print bestAnswer.find('img')
     <img src="/@@/favourite-yes" ... title="Marked as best answer" />
 
-    >>> print soup.first(
+    >>> print soup.find(
     ...     'div', 'boardCommentBody highlighted').renderContents()
     <p>New version of the firefox package are available with SVG support
     enabled. You can use apt-get or adept to upgrade.</p>
@@ -286,11 +286,11 @@
 answerer back to None.
 
     >>> soup = find_main_content(owner_browser.contents)
-    >>> bestAnswer = soup.fetch('div', 'boardComment')[-4]
-    >>> bestAnswer.first('strong') is None
+    >>> bestAnswer = soup.findAll('div', 'boardComment')[-4]
+    >>> bestAnswer.find('strong') is None
     True
 
-    >>> bestAnswer.first('div', 'boardCommentBody')
+    >>> bestAnswer.find('div', 'boardCommentBody')
     <div class="boardCommentBody" itemprop="commentText"><p>New version
     of the firefox package
     are available with SVG support enabled. You can use apt-get or adept to
@@ -325,7 +325,7 @@
 
     >>> soup = find_tag_by_id(owner_browser.contents, 'portlet-details')
     >>> soup = find_main_content(owner_browser.contents)
-    >>> bestAnswer = soup.first('img', {'title': 'Marked as best answer'})
+    >>> bestAnswer = soup.find('img', {'title': 'Marked as best answer'})
     >>> None == bestAnswer
     True
 
@@ -382,17 +382,17 @@
 It lists all the actions performed through workflow on the question:
 
     >>> soup = find_main_content(anon_browser.contents)
-    >>> action_listing = soup.first('table', 'listing')
-    >>> for header in action_listing.fetch('th'):
+    >>> action_listing = soup.find('table', 'listing')
+    >>> for header in action_listing.findAll('th'):
     ...     print header.renderContents()
     When
     Who
     Action
     New State
 
-    >>> for row in action_listing.first('tbody').fetch('tr'):
-    ...     cells = row.fetch('td')
-    ...     who = extract_text(cells[1].first('a'))
+    >>> for row in action_listing.find('tbody').findAll('tr'):
+    ...     cells = row.findAll('td')
+    ...     who = extract_text(cells[1].find('a'))
     ...     action = cells[2].renderContents()
     ...     new_status = cells[3].renderContents()
     ...     print who.lstrip('&nbsp;'), action, new_status

=== modified file 'lib/lp/answers/stories/questions-index.txt'
--- lib/lp/answers/stories/questions-index.txt	2011-12-24 15:18:32 +0000
+++ lib/lp/answers/stories/questions-index.txt	2017-10-23 00:36:01 +0000
@@ -24,10 +24,10 @@
 
     >>> latest_questions_asked = find_tag_by_id(
     ...     anon_browser.contents, 'latest-questions-asked')
-    >>> print latest_questions_asked.first('h2').renderContents()
+    >>> print latest_questions_asked.find('h2').renderContents()
     Latest questions asked
-    >>> for row in latest_questions_asked.fetch('li'):
-    ...     row.first('a').renderContents()
+    >>> for row in latest_questions_asked.findAll('li'):
+    ...     row.find('a').renderContents()
     '...: Problemas de Impress\xc3\xa3o no Firefox'
     '...: Problema al recompilar kernel con soporte smp (doble-n\xc3\xbacleo)'
     '...: Continue playing after shutdown'
@@ -38,10 +38,10 @@
 
     >>> latest_questions_solved = find_tag_by_id(
     ...     anon_browser.contents, 'latest-questions-solved')
-    >>> print latest_questions_solved.first('h2').renderContents()
+    >>> print latest_questions_solved.find('h2').renderContents()
     Latest questions solved
-    >>> for row in latest_questions_solved.fetch('li'):
-    ...     row.first('a').renderContents()
+    >>> for row in latest_questions_solved.findAll('li'):
+    ...     row.find('a').renderContents()
     '...: mailto: problem in webpage'
 
 The application footer also contains a sample of stats for the application:

=== modified file 'lib/lp/blueprints/stories/blueprints/xx-buglinks.txt'
--- lib/lp/blueprints/stories/blueprints/xx-buglinks.txt	2011-03-17 02:34:25 +0000
+++ lib/lp/blueprints/stories/blueprints/xx-buglinks.txt	2017-10-23 00:36:01 +0000
@@ -41,7 +41,7 @@
 link.
 
     >>> soup = find_main_content(user_browser.contents)
-    >>> soup.first('div', 'informational message')
+    >>> soup.find('div', 'informational message')
     <div class="informational message">Added link to bug #4:
     ...Reflow problems with complex page layouts...</div>
 
@@ -64,5 +64,5 @@
 A confirmation is displayed to the user.
 
     >>> soup = find_main_content(user_browser.contents)
-    >>> soup.first('div', 'informational message')
+    >>> soup.find('div', 'informational message')
     <div class="informational message">Removed link to bug #4.</div>

=== modified file 'lib/lp/blueprints/stories/sprints/xx-sprints.txt'
--- lib/lp/blueprints/stories/sprints/xx-sprints.txt	2017-04-10 10:49:19 +0000
+++ lib/lp/blueprints/stories/sprints/xx-sprints.txt	2017-10-23 00:36:01 +0000
@@ -380,7 +380,7 @@
     >>> def print_attendees(sprint_page):
     ...     """Print the attendees listed in the attendees portlet."""
     ...     attendees_portlet = find_portlet(sprint_page, 'Attendees')
-    ...     for li in attendees_portlet.fetch('ul')[0].fetch('li'):
+    ...     for li in attendees_portlet.findAll('ul')[0].findAll('li'):
     ...         print li.a.string.encode('ascii', 'xmlcharrefreplace')
 
     >>> print_attendees(browser.contents)

=== modified file 'lib/lp/blueprints/stories/standalone/subscribing.txt'
--- lib/lp/blueprints/stories/standalone/subscribing.txt	2012-09-19 04:09:06 +0000
+++ lib/lp/blueprints/stories/standalone/subscribing.txt	2017-10-23 00:36:01 +0000
@@ -162,7 +162,7 @@
     >>> subscribers = find_tags_by_class(browser.contents, 'subscriber')
     >>> for subscriber in subscribers:
     ...     a_tags = subscriber.findAll('a')
-    ...     img = a_tags[0].first('img')
+    ...     img = a_tags[0].find('img')
     ...     print img['src'],
     ...     print a_tags[1].string
     /@@/subscriber-essential Stuart Bishop
@@ -187,7 +187,7 @@
     >>> subscribers = find_tags_by_class(browser.contents, 'subscriber')
     >>> for subscriber in subscribers:
     ...     a_tags = subscriber.findAll('a')
-    ...     img = a_tags[0].first('img')
+    ...     img = a_tags[0].find('img')
     ...     print img['src'],
     ...     print a_tags[1].string
     /@@/subscriber-inessential Stuart Bishop
@@ -320,7 +320,7 @@
     >>> subscribers = find_tags_by_class(browser.contents, 'subscriber')
     >>> for subscriber in subscribers:
     ...     a_tags = subscriber.findAll('a')
-    ...     img = a_tags[0].first('img')
+    ...     img = a_tags[0].find('img')
     ...     print img['src'],
     ...     print a_tags[1].string
     /@@/subscriber-essential Andrew Bennetts

=== modified file 'lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt'
--- lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt	2013-09-27 04:13:23 +0000
+++ lib/lp/bugs/stories/bug-also-affects/xx-duplicate-bugwatches.txt	2017-10-23 00:36:01 +0000
@@ -20,7 +20,7 @@
 
     >>> bugwatch_portlet = find_portlet(
     ...     user_browser.contents, 'Remote bug watches')
-    >>> for li_tag in bugwatch_portlet.fetch('li'):
+    >>> for li_tag in bugwatch_portlet.findAll('li'):
     ...     print li_tag.findAll('a')[0].renderContents()
     debbugs #42
 
@@ -46,7 +46,7 @@
 
     >>> bugwatch_portlet = find_portlet(
     ...     user_browser.contents, 'Remote bug watches')
-    >>> for li_tag in bugwatch_portlet.fetch('li'):
+    >>> for li_tag in bugwatch_portlet.findAll('li'):
     ...     print li_tag.findAll('a')[0].string
     debbugs #42
 

=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-single-comment-view.txt'
--- lib/lp/bugs/stories/bugs/xx-bug-single-comment-view.txt	2009-06-12 16:36:02 +0000
+++ lib/lp/bugs/stories/bugs/xx-bug-single-comment-view.txt	2017-10-23 00:36:01 +0000
@@ -10,7 +10,7 @@
     ...     soup = find_main_content(browser.contents)
     ...     comment_details = soup('div', 'boardCommentDetails')
     ...     for details in comment_details:
-    ...         print details.first('strong').string
+    ...         print details.find('strong').string
 
     >>> print_comment_titles(browser.contents)
     Fantastic idea, I'd really like to see this

=== modified file 'lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt'
--- lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt	2017-10-23 00:36:01 +0000
@@ -205,9 +205,9 @@
 
     >>> def names_and_branches(contents):
     ...     listing = find_tag_by_id(contents, 'bugs-table-listing')
-    ...     for row in listing.fetch(None, {'class': 'buglisting-row'}):
+    ...     for row in listing.findAll(None, {'class': 'buglisting-row'}):
     ...         badge_cell = row.find(None, {'class': 'bug-related-icons'})
-    ...         spans = badge_cell.fetch('span')
+    ...         spans = badge_cell.findAll('span')
     ...         for span in spans:
     ...            print "  Badge:", span.get('alt')
 

=== modified file 'lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt'
--- lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt	2009-08-19 13:10:19 +0000
+++ lib/lp/bugs/stories/bugwatches/xx-bugtask-bugwatch-linkage.txt	2017-10-23 00:36:01 +0000
@@ -116,7 +116,7 @@
     'http://bugs.launchpad.dev/debian/+source/mozilla-firefox/+bug/1'
 
     >>> bugwatch_portlet = find_portlet(browser.contents, 'Remote bug watches')
-    >>> for li_tag in bugwatch_portlet.fetch('li'):
+    >>> for li_tag in bugwatch_portlet.findAll('li'):
     ...     print li_tag.findAll('a')[0].string
     mozilla.org #123543
     mozilla.org #2000

=== modified file 'lib/lp/bugs/stories/cve/cve-linking.txt'
--- lib/lp/bugs/stories/cve/cve-linking.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/bugs/stories/cve/cve-linking.txt	2017-10-23 00:36:01 +0000
@@ -62,7 +62,7 @@
 A notification is displayed telling the user which bug they just linked:
 
     >>> soup = find_main_content(user_browser.contents)
-    >>> soup.first('div', 'informational message')
+    >>> soup.find('div', 'informational message')
     <div class="informational message">Added link to bug #2:
     ...Blackhole Trash folder...</div>
 

=== modified file 'lib/lp/bugs/tests/bug.py'
--- lib/lp/bugs/tests/bug.py	2017-10-23 00:36:01 +0000
+++ lib/lp/bugs/tests/bug.py	2017-10-23 00:36:01 +0000
@@ -80,7 +80,7 @@
         :param highlighted_only: Only print the highlighted row
     """
     main_content = find_main_content(content)
-    affects_table = main_content.first('table', {'class': 'listing'})
+    affects_table = main_content.find('table', {'class': 'listing'})
     if highlighted_only:
         tr_attrs = {'class': 'highlight'}
     else:

=== modified file 'lib/lp/code/stories/branches/xx-bazaar-home.txt'
--- lib/lp/code/stories/branches/xx-bazaar-home.txt	2012-09-12 06:13:41 +0000
+++ lib/lp/code/stories/branches/xx-bazaar-home.txt	2017-10-23 00:36:01 +0000
@@ -34,7 +34,7 @@
     Most active projects in the last month
     see all projects&#8230;
 
-    >>> print preview.fetch('a')[-1]['href']
+    >>> print preview.findAll('a')[-1]['href']
     /projects
 
 
@@ -72,7 +72,7 @@
 registered branches first.
 
     >>> registered = find_tag_by_id(browser.contents, 'recently-registered')
-    >>> print registered.fetch('a')[-1]['href']
+    >>> print registered.findAll('a')[-1]['href']
     /+recently-registered-branches
 
     >>> browser.getLink(url='recently-registered-branches').click()
@@ -84,7 +84,7 @@
 registered is the ordering, the registered date is also shown.
 
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.thead.fetch('tr'):
+    >>> for row in table.thead.findAll('tr'):
     ...     print extract_text(row)
     Name
     Status
@@ -105,7 +105,7 @@
 
     >>> browser.open('http://code.launchpad.dev/')
     >>> changed = find_tag_by_id(browser.contents, 'recently-changed')
-    >>> print changed.fetch('a')[-1]['href']
+    >>> print changed.findAll('a')[-1]['href']
     /+recently-changed-branches
 
     >>> browser.getLink(url='recently-changed-branches').click()
@@ -113,7 +113,7 @@
     Recently changed branches
 
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.thead.fetch('tr'):
+    >>> for row in table.thead.findAll('tr'):
     ...     print extract_text(row)
     Name
     Status
@@ -132,7 +132,7 @@
 
     >>> browser.open('http://code.launchpad.dev/')
     >>> imported = find_tag_by_id(browser.contents, 'recent-imports')
-    >>> print imported.fetch('a')[-1]['href']
+    >>> print imported.findAll('a')[-1]['href']
     /+recently-imported-branches
 
     >>> browser.getLink(url='recently-imported-branches').click()
@@ -144,7 +144,7 @@
 imported branch listings.
 
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.thead.fetch('tr'):
+    >>> for row in table.thead.findAll('tr'):
     ...     print extract_text(row)
     Name
     Status

=== modified file 'lib/lp/code/stories/branches/xx-branch-listings-merge-proposal-badge.txt'
--- lib/lp/code/stories/branches/xx-branch-listings-merge-proposal-badge.txt	2015-06-02 06:35:38 +0000
+++ lib/lp/code/stories/branches/xx-branch-listings-merge-proposal-badge.txt	2017-10-23 00:36:01 +0000
@@ -2,10 +2,10 @@
 
     >>> def branchSummary(browser):
     ...     table = find_tag_by_id(browser.contents, 'branchtable')
-    ...     for row in table.tbody.fetch('tr'):
+    ...     for row in table.tbody.findAll('tr'):
     ...         cells = row.findAll('td')
     ...         first_cell = cells[0]
-    ...         anchors = first_cell.fetch('a')
+    ...         anchors = first_cell.findAll('a')
     ...         print anchors[0].get('href')
     ...         # Badges in the next cell
     ...         for img in cells[1].findAll('img'):

=== modified file 'lib/lp/code/stories/branches/xx-branch-listings.txt'
--- lib/lp/code/stories/branches/xx-branch-listings.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/code/stories/branches/xx-branch-listings.txt	2017-10-23 00:36:01 +0000
@@ -28,7 +28,7 @@
     ...1...&rarr;...6...of 10 results...
 
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.thead.fetch('tr'):
+    >>> for row in table.thead.findAll('tr'):
     ...     print extract_text(row)
     Name
     Status
@@ -39,7 +39,7 @@
 fields.  There are a couple of branches that have them, but most don't
 and are really just branch metadata without the revisions behind them.
 
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~name12/firefox/main                Development  ...
     lp://dev/~name12/gnome-terminal/2.6          Mature       ...
@@ -55,7 +55,7 @@
     ...7...&rarr;...10...of 10 results...
 
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~name12/gnome-terminal/klingon          Experimental  ...
     lp://dev/~name12/+junk/junk.contrib              Development   ...
@@ -82,7 +82,7 @@
 
     >>> browser.open('http://code.launchpad.dev/~name12')
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~name12/firefox/main                 Development  ...
     lp://dev/~name12/gnome-terminal/2.6           Mature       ...
@@ -117,7 +117,7 @@
     ...1...&rarr;...6...of 12 results...
 
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~name12/firefox/main                 Development    ...
     lp://dev/~name12/gnome-terminal/2.4           Abandoned      ...
@@ -133,7 +133,7 @@
     ...7...&rarr;...12...of 12 results...
 
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~name12/gnome-terminal/pushed         Development     ...
     lp://dev/~name12/gnome-terminal/scanned        Development     ...
@@ -148,7 +148,7 @@
     >>> browser.getControl(name='field.lifecycle').displayValue = ['Abandoned']
     >>> browser.getControl('Filter').click()
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~name12/gnome-terminal/2.4    Abandoned     ...
 
@@ -160,7 +160,7 @@
     >>> browser.getControl(name='field.lifecycle').displayValue
     ['Any active status']
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~name12/firefox/main                  Development  ...
     lp://dev/~name12/gnome-terminal/2.6            Mature       ...
@@ -188,7 +188,7 @@
     ...     'http://code.launchpad.dev/~name12/+branches?'
     ...     'field.category=subscribed')
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~name12/firefox/main ...
     lp://dev/~launchpad/gnome-terminal/launchpad ...
@@ -212,12 +212,12 @@
 
     >>> def branchSummary(browser):
     ...     table = find_tag_by_id(browser.contents, 'branchtable')
-    ...     for row in table.tbody.fetch('tr'):
+    ...     for row in table.tbody.findAll('tr'):
     ...         if row.getText().startswith('A development focus branch'):
     ...             continue
     ...         cells = row.findAll('td')
     ...         first_cell = cells[0]
-    ...         anchors = first_cell.fetch('a')
+    ...         anchors = first_cell.findAll('a')
     ...         print anchors[0].get('href')
     ...         # Badges in the next cell
     ...         for img in cells[1].findAll('img'):
@@ -334,7 +334,7 @@
 
     >>> browser.open('http://code.launchpad.dev/gnome-terminal/+branches')
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     A development focus ...
     lp://dev/~name12/gnome-terminal/2.6            Mature       ...
@@ -347,7 +347,7 @@
     >>> browser.getControl(name='field.sort_by').value = ['by branch name']
     >>> browser.getControl('Filter').click()
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     A development focus ...
     lp://dev/~name12/gnome-terminal/2.6             Mature          ...
@@ -380,8 +380,8 @@
     >>> browser.open('http://code.launchpad.dev/gnome-terminal')
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
     >>> # The development focus is always first.
-    >>> row = table.tbody.fetch('tr')[0]
-    >>> cols = row.fetch('td')
+    >>> row = table.tbody.findAll('tr')[0]
+    >>> cols = row.findAll('td')
     >>> print extract_text(cols[0])
     lp://dev/gnome-terminal     Series: trunk
 
@@ -408,7 +408,7 @@
 
     >>> browser.open('http://code.launchpad.dev/gnome-terminal')
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> print extract_text(table.tbody.fetch('tr')[0])
+    >>> print extract_text(table.tbody.findAll('tr')[0])
     lp://dev/gnome-terminal  Series: trunk, alpha, pre-1.0  ...
 
 
@@ -421,7 +421,7 @@
 
     >>> browser.open('http://code.launchpad.dev/gnome-terminal')
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/gnome-terminal   Series: trunk...    Development  ...
     lp://dev/~name12/gnome-terminal/2.6           Mature       ...
@@ -446,7 +446,7 @@
     >>> browser.getControl(name='field.lifecycle').displayValue = ['Experimental']
     >>> browser.getControl('Filter').click()
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~name12/gnome-terminal/klingon       Experimental ...
 
@@ -456,7 +456,7 @@
     >>> browser.getControl(name='field.lifecycle').displayValue = ['Development']
     >>> browser.getControl('Filter').click()
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/gnome-terminal   Series: trunk...    Development  ...
 

=== modified file 'lib/lp/code/stories/branches/xx-branch-tag-cloud.txt'
--- lib/lp/code/stories/branches/xx-branch-tag-cloud.txt	2010-08-31 00:29:48 +0000
+++ lib/lp/code/stories/branches/xx-branch-tag-cloud.txt	2017-10-23 00:36:01 +0000
@@ -24,7 +24,7 @@
 the link is shown.
 
     >>> tags = find_tag_by_id(anon_browser.contents, 'project-tags')
-    >>> for anchor in tags.fetch('a'):
+    >>> for anchor in tags.findAll('a'):
     ...     print anchor.renderContents(), anchor['class']
     linux cloud-size-largest cloud-medium
     wibble cloud-size-smallest cloud-dark

=== modified file 'lib/lp/code/stories/branches/xx-person-branches.txt'
--- lib/lp/code/stories/branches/xx-person-branches.txt	2016-07-02 07:56:08 +0000
+++ lib/lp/code/stories/branches/xx-person-branches.txt	2017-10-23 00:36:01 +0000
@@ -46,7 +46,7 @@
 
     >>> browser.open('http://code.launchpad.dev/~name12')
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~name12/landscape/feature-x      Development
     ...
@@ -64,7 +64,7 @@
     >>> print browser.title
     Code : Sample Person
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~name12/landscape/feature-x      Development
     ...
@@ -83,7 +83,7 @@
     >>> print browser.title
     Code : Sample Person
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~launchpad/gnome-terminal/launchpad  Development           ...
     lp://dev/~name12/+junk/junk.dev               Experimental  ...

=== modified file 'lib/lp/code/stories/branches/xx-private-branch-listings.txt'
--- lib/lp/code/stories/branches/xx-private-branch-listings.txt	2017-04-18 22:17:00 +0000
+++ lib/lp/code/stories/branches/xx-private-branch-listings.txt	2017-10-23 00:36:01 +0000
@@ -49,7 +49,7 @@
     >>> def print_recently_registered_branches(browser):
     ...     browser.open('http://code.launchpad.dev')
     ...     branches = find_tag_by_id(browser.contents, 'recently-registered')
-    ...     for list_item in branches.ul.fetch('li'):
+    ...     for list_item in branches.ul.findAll('li'):
     ...         print "%r" % list_item.renderContents()
 
 When there is no logged in user, only public branches should be visible.
@@ -113,7 +113,7 @@
     ...         print extract_text(find_tag_by_id(
     ...             browser.contents, 'branch-summary'))
     ...     else:
-    ...         for row in table.tbody.fetch('tr'):
+    ...         for row in table.tbody.findAll('tr'):
     ...             print extract_text(row)
 
     >>> print_landscape_code_listing(anon_browser)
@@ -153,7 +153,7 @@
     ...     browser.open(full_url)
     ...     table = find_tag_by_id(browser.contents, 'branchtable')
     ...     branches = []
-    ...     for row in table.tbody.fetch('tr'):
+    ...     for row in table.tbody.findAll('tr'):
     ...         branches.append(extract_text(row))
     ...     landscape_branches = [branch for branch in branches
     ...                           if 'landscape' in branch]

=== modified file 'lib/lp/code/stories/branches/xx-product-branches.txt'
--- lib/lp/code/stories/branches/xx-product-branches.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/code/stories/branches/xx-product-branches.txt	2017-10-23 00:36:01 +0000
@@ -54,7 +54,7 @@
 
 The 'Help' links go to the help wiki.
 
-    >>> for anchor in summary.fetch('a'):
+    >>> for anchor in summary.findAll('a'):
     ...     print anchor['href']
     https://help.launchpad.net/Code
 
@@ -123,7 +123,7 @@
 
     >>> browser.open('http://code.launchpad.dev/firefox')
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr')[0:2]:
+    >>> for row in table.tbody.findAll('tr')[0:2]:
     ...     print extract_text(row)
     lp://dev/firefox
       Series: trunk, 1.0                     Development ...
@@ -138,7 +138,7 @@
 
     >>> browser.open('http://code.launchpad.dev/firefox')
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr')[0:2]:
+    >>> for row in table.tbody.findAll('tr')[0:2]:
     ...     print extract_text(row)
     lp://dev/firefox
       Series: trunk                 Development ...
@@ -159,7 +159,7 @@
 
     >>> browser.open('http://code.launchpad.dev/firefox')
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr')[0:2]:
+    >>> for row in table.tbody.findAll('tr')[0:2]:
     ...     print extract_text(row)
     lp://dev/~mark/firefox/release-0.8     Development ...
 

=== modified file 'lib/lp/code/stories/branches/xx-product-overview.txt'
--- lib/lp/code/stories/branches/xx-product-overview.txt	2009-04-17 10:32:16 +0000
+++ lib/lp/code/stories/branches/xx-product-overview.txt	2017-10-23 00:36:01 +0000
@@ -10,7 +10,7 @@
     ...     if branches is None:
     ...         print "No 'Latest branches' portlet found at %s" % (url,)
     ...         return
-    ...     for list_item in branches.fetch('li'):
+    ...     for list_item in branches.findAll('li'):
     ...         print extract_text(list_item)
 
     >>> def make_branch_on_product(product, branch_name, person_name):

=== modified file 'lib/lp/code/stories/branches/xx-project-branches.txt'
--- lib/lp/code/stories/branches/xx-project-branches.txt	2011-05-05 09:37:10 +0000
+++ lib/lp/code/stories/branches/xx-project-branches.txt	2017-10-23 00:36:01 +0000
@@ -24,7 +24,7 @@
 
     >>> browser.open('http://code.launchpad.dev/mozilla')
     >>> table = find_tag_by_id(browser.contents, 'branchtable')
-    >>> for row in table.tbody.fetch('tr'):
+    >>> for row in table.tbody.findAll('tr'):
     ...     print extract_text(row)
     lp://dev/~mark/firefox/release--0.9.1  Development   firefox ...
     lp://dev/~mark/firefox/release-0.8     Development   firefox ...

=== modified file 'lib/lp/code/stories/branches/xx-source-package-branches-listing.txt'
--- lib/lp/code/stories/branches/xx-source-package-branches-listing.txt	2014-02-25 06:38:58 +0000
+++ lib/lp/code/stories/branches/xx-source-package-branches-listing.txt	2017-10-23 00:36:01 +0000
@@ -34,7 +34,7 @@
 
     >>> def print_branches(browser):
     ...    table = find_tag_by_id(browser.contents, 'branchtable')
-    ...    for row in table.tbody.fetch('tr'):
+    ...    for row in table.tbody.findAll('tr'):
     ...        print extract_text(row)
     >>> print_branches(browser)
     lp://dev/~owner1/distro/series/foo/branch1 ...

=== modified file 'lib/lp/code/stories/branches/xx-subscribing-branches.txt'
--- lib/lp/code/stories/branches/xx-subscribing-branches.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/code/stories/branches/xx-subscribing-branches.txt	2017-10-23 00:36:01 +0000
@@ -9,7 +9,7 @@
     ...     if subscriptions == None:
     ...         print subscriptions
     ...         return
-    ...     for subscriber in subscriptions.fetch('div'):
+    ...     for subscriber in subscriptions.findAll('div'):
     ...         print extract_text(subscriber.renderContents())
 
 Another to print the informational message.

=== modified file 'lib/lp/code/stories/codeimport/xx-codeimport-results.txt'
--- lib/lp/code/stories/codeimport/xx-codeimport-results.txt	2011-12-20 23:28:22 +0000
+++ lib/lp/code/stories/codeimport/xx-codeimport-results.txt	2017-10-23 00:36:01 +0000
@@ -52,7 +52,7 @@
 
     >>> # The ordering here is dependant on the order the status values
     >>> # are declared in the enumeration.
-    >>> for img in import_results.fetch('img'):
+    >>> for img in import_results.findAll('img'):
     ...     print img
     <img src="/@@/no" title="Unsupported feature" />
     <img src="/@@/no" title="Foreign branch invalid" />
@@ -64,7 +64,7 @@
 
     >>> browser.open(branch_url_2)
     >>> import_results = find_tag_by_id(browser.contents, 'import-results')
-    >>> for img in import_results.fetch('img'):
+    >>> for img in import_results.findAll('img'):
     ...     print img
     <img src="/@@/no" title="Job killed" />
     <img src="/@@/no" title="Job reclaimed" />

=== modified file 'lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt'
--- lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt	2016-10-14 16:16:18 +0000
+++ lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt	2017-10-23 00:36:01 +0000
@@ -7,12 +7,12 @@
 
     >>> def print_recipe_listing_head(browser):
     ...     table = find_tag_by_id(browser.contents, 'recipetable')
-    ...     for row in table.thead.fetch('tr'):
+    ...     for row in table.thead.findAll('tr'):
     ...         print extract_text(row)
 
     >>> def print_recipe_listing_contents(browser):
     ...     table = find_tag_by_id(browser.contents, 'recipetable')
-    ...     for row in table.tbody.fetch('tr'):
+    ...     for row in table.tbody.findAll('tr'):
     ...         print extract_text(row)
 
 

=== modified file 'lib/lp/coop/answersbugs/stories/question-buglink.txt'
--- lib/lp/coop/answersbugs/stories/question-buglink.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/coop/answersbugs/stories/question-buglink.txt	2017-10-23 00:36:01 +0000
@@ -33,7 +33,7 @@
 message is displayed:
 
     >>> soup = find_main_content(user_browser.contents)
-    >>> soup.first('div', 'message')
+    >>> soup.find('div', 'message')
     <div class="message">Not a valid bug number or nickname.</div>
 
 The user is offered a link to search for bug in case they don't know the
@@ -82,7 +82,7 @@
     >>> user_browser.url
     '.../firefox/+question/2'
     >>> soup = find_main_content(user_browser.contents)
-    >>> soup.first('div', 'informational message')
+    >>> soup.find('div', 'informational message')
     <div class="informational message">Removed link to bug #...</div>
     >>> print extract_text(
     ...     find_tag_by_id(user_browser.contents, 'related-bugs'))

=== modified file 'lib/lp/coop/answersbugs/stories/question-makebug.txt'
--- lib/lp/coop/answersbugs/stories/question-makebug.txt	2012-06-16 13:31:38 +0000
+++ lib/lp/coop/answersbugs/stories/question-makebug.txt	2017-10-23 00:36:01 +0000
@@ -53,7 +53,7 @@
 questions' portlet:
 
   >>> portlet = find_portlet(browser.contents, 'Related questions')
-  >>> for question in portlet.fetch('li', 'question-row'):
+  >>> for question in portlet.findAll('li', 'question-row'):
   ...     print question.renderContents()
   <span class="sprite question">Mozilla Firefox</span>: ...<a href=".../firefox/+question/2">Problem...
 

=== modified file 'lib/lp/soyuz/stories/ppa/xx-private-ppa-presentation.txt'
--- lib/lp/soyuz/stories/ppa/xx-private-ppa-presentation.txt	2017-10-23 00:36:01 +0000
+++ lib/lp/soyuz/stories/ppa/xx-private-ppa-presentation.txt	2017-10-23 00:36:01 +0000
@@ -9,7 +9,7 @@
 
     >>> browser.open("http://launchpad.dev/~cprov/+archive";)
     >>> from lp.services.beautifulsoup import BeautifulSoup
-    >>> body_el = BeautifulSoup(browser.contents).first('body')
+    >>> body_el = BeautifulSoup(browser.contents).find('body')
     >>> 'private' in body_el['class']
     False
 
@@ -33,6 +33,6 @@
     >>> cprov_browser = setupBrowser(
     ...     auth='Basic celso.providelo@xxxxxxxxxxxxx:test')
     >>> cprov_browser.open("http://launchpad.dev/~cprov/+archive/p3a";)
-    >>> body_el = BeautifulSoup(cprov_browser.contents).first('body')
+    >>> body_el = BeautifulSoup(cprov_browser.contents).find('body')
     >>> 'private' in body_el['class']
     True

=== modified file 'lib/lp/translations/stories/standalone/xx-person-editlanguages.txt'
--- lib/lp/translations/stories/standalone/xx-person-editlanguages.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/translations/stories/standalone/xx-person-editlanguages.txt	2017-10-23 00:36:01 +0000
@@ -105,7 +105,7 @@
 
     >>> print find_spoken_languages(country_portlet)
     []
-    >>> print country_portlet.first('a')['href']
+    >>> print country_portlet.find('a')['href']
     http://answers.launchpad.dev/launchpad
 
 Back home in Brazil, Joao gets the equivalent for Brazil, where the

=== modified file 'lib/lp/translations/stories/standalone/xx-pofile-export.txt'
--- lib/lp/translations/stories/standalone/xx-pofile-export.txt	2015-07-21 09:04:01 +0000
+++ lib/lp/translations/stories/standalone/xx-pofile-export.txt	2017-10-23 00:36:01 +0000
@@ -86,7 +86,7 @@
     ...     browser.contents, 'Translation file details')
     >>> carlos = u'Carlos Perell\xf3 Mar\xedn'
     >>> creator = extract_text(
-    ...     translation_portlet.firstText('Creator:').findNext('a'))
+    ...     translation_portlet.find(text='Creator:').findNext('a'))
     >>> carlos in creator
     True
 

=== modified file 'lib/lp/translations/stories/translationgroups/xx-translationgroups.txt'
--- lib/lp/translations/stories/translationgroups/xx-translationgroups.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/translations/stories/translationgroups/xx-translationgroups.txt	2017-10-23 00:36:01 +0000
@@ -37,7 +37,7 @@
     >>> admin_browser.open(
     ...     'http://translations.launchpad.dev/+groups/+new')
     >>> print find_main_content(
-    ...     admin_browser.contents).first('h1').renderContents()
+    ...     admin_browser.contents).find('h1').renderContents()
     Create a new translation group
 
 Translation group names must meet certain conditions.  For example, they


Follow ups