This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 83b3886bde52a13014a00ac59948107501cd3a55
Author: Guillermo Cruz <[email protected]>
AuthorDate: Tue Feb 11 15:51:41 2025 -0700

    [#8575] replacing Beutifulsoup func findAll with find_all
---
 Allura/allura/lib/markdown_extensions.py           |  4 +-
 Allura/allura/scripts/trac_export.py               |  6 +-
 Allura/allura/tests/functional/test_admin.py       | 84 ++++++++++----------
 Allura/allura/tests/functional/test_auth.py        |  6 +-
 Allura/allura/tests/functional/test_discuss.py     | 28 +++----
 Allura/allura/tests/functional/test_home.py        |  8 +-
 Allura/allura/tests/functional/test_nav.py         | 10 +--
 .../tests/functional/test_personal_dashboard.py    |  2 +-
 Allura/allura/tests/functional/test_root.py        | 32 ++++----
 Allura/allura/tests/functional/test_site_admin.py  | 40 +++++-----
 .../allura/tests/functional/test_user_profile.py   |  2 +-
 Allura/allura/tests/test_webhooks.py               |  4 +-
 AlluraTest/alluratest/controller.py                |  2 +-
 .../forgeactivity/tests/functional/test_root.py    |  2 +-
 .../forgediscussion/tests/functional/test_forum.py | 72 ++++++++---------
 .../tests/functional/test_forum_admin.py           | 14 ++--
 .../tests/functional/test_import.py                |  6 +-
 .../forgediscussion/tests/functional/test_rest.py  |  2 +-
 .../forgegit/tests/functional/test_controllers.py  | 30 +++----
 ForgeImporters/forgeimporters/github/wiki.py       |  2 +-
 .../forgesvn/tests/functional/test_controllers.py  |  6 +-
 .../forgetracker/tests/functional/test_root.py     | 92 +++++++++++-----------
 ForgeWiki/forgewiki/converters.py                  |  2 +-
 ForgeWiki/forgewiki/tests/functional/test_root.py  |  8 +-
 24 files changed, 232 insertions(+), 232 deletions(-)

diff --git a/Allura/allura/lib/markdown_extensions.py 
b/Allura/allura/lib/markdown_extensions.py
index 28ffd13aa..0228cc98b 100644
--- a/Allura/allura/lib/markdown_extensions.py
+++ b/Allura/allura/lib/markdown_extensions.py
@@ -485,9 +485,9 @@ def run(self, text: str):
             rewrite = self._rewrite_abs
         else:
             rewrite = self._rewrite
-        for link in soup.findAll('a'):
+        for link in soup.find_all('a'):
             rewrite(link, 'href')
-        for link in soup.findAll('img'):
+        for link in soup.find_all('img'):
             rewrite(link, 'src')
 
         # html5lib parser adds html/head/body tags, so output <body> without 
its own tags
diff --git a/Allura/allura/scripts/trac_export.py 
b/Allura/allura/scripts/trac_export.py
index c9f5a0e70..88b55496f 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -173,7 +173,7 @@ def parse_ticket(self, id):
             desc.renderContents('utf8').decode('utf8')) if desc else ''
         comments = []
         relative_base_url = 
six.moves.urllib.parse.urlparse(self.full_url(self.TICKET_URL % '')).path
-        for comment in d.findAll('form', action='#comment'):
+        for comment in d.find_all('form', action='#comment'):
             c = {}
             c['submitter'] = re.sub(
                 r'.* by ', '', comment.find('h3', 'change').text).strip()
@@ -222,7 +222,7 @@ def parse_ticket_attachments(self, id):
                 if desc_el:
                     # TODO: Convert to Allura link syntax as needed
                     d['description'] = ''.join(
-                        desc_el.findAll(string=True)).strip()
+                        desc_el.find_all(string=True)).strip()
             list.append(d)
         return list
 
@@ -295,7 +295,7 @@ def next(self):
     __next__ = next
 
     def clean_missing_wiki_links(self, doc):
-        for link in doc.findAll('a', 'missing wiki'):
+        for link in doc.find_all('a', 'missing wiki'):
             link.string = link.string.rstrip('?')
 
 
diff --git a/Allura/allura/tests/functional/test_admin.py 
b/Allura/allura/tests/functional/test_admin.py
index 23b8301f0..c3b4c5cad 100644
--- a/Allura/allura/tests/functional/test_admin.py
+++ b/Allura/allura/tests/functional/test_admin.py
@@ -105,7 +105,7 @@ def test_admin_controller(self):
         assert 'error' not in self.webflash(r)
         # check tool in the nav
         r = self.app.get('/p/test/test-tool/').follow()
-        active_link = r.html.findAll('li', {'class': 'selected'})
+        active_link = r.html.find_all('li', {'class': 'selected'})
         assert len(active_link) == 1
         assert active_link[0].contents[1]['href'] == '/p/test/test-tool/'
         with audits('install tool test-tool2'):
@@ -118,11 +118,11 @@ def test_admin_controller(self):
         assert 'error' not in self.webflash(r)
         # check the nav - tools of same type are grouped
         r = self.app.get('/p/test/test-tool/Home/')
-        active_link = r.html.findAll('li', {'class': 'selected'})
+        active_link = r.html.find_all('li', {'class': 'selected'})
         assert len(active_link) == 2
         assert active_link[0].contents[1]['href'] == '/p/test/_list/wiki'
-        assert r.html.findAll('a', {'href': '/p/test/test-tool2/'})
-        assert r.html.findAll('a', {'href': '/p/test/test-tool/'})
+        assert r.html.find_all('a', {'href': '/p/test/test-tool2/'})
+        assert r.html.find_all('a', {'href': '/p/test/test-tool/'})
 
         # check can't create dup tool
         r = self.app.post('/admin/update_mounts', params={
@@ -169,15 +169,15 @@ def test_features(self):
                 'features-1.feature': '  ',
                 'features-2.feature': ' Two '})
             if resp.status_int == 200:
-                errors = resp.html.findAll(attrs={'class': 'fielderror'})
+                errors = resp.html.find_all(attrs={'class': 'fielderror'})
                 assert [] == errors
-                errors = resp.html.findAll(attrs={'class': 'error'})
+                errors = resp.html.find_all(attrs={'class': 'error'})
                 assert [] == errors
                 raise AssertionError('Should be a 301 not 200 response')
 
         r = self.app.get('/admin/overview')
         features = r.html.find('div', {'id': 'features'})
-        features = features.findAll('input', {'type': 'text'})
+        features = features.find_all('input', {'type': 'text'})
         # two features + extra empty input + stub hidden input for js
         assert len(features) == 2+1+1
         assert features[0]['value'] == 'One'
@@ -317,7 +317,7 @@ def test_tool_permissions(self):
                     'new.mount_label': tool})
             r = self.app.get('/admin/test-%d/permissions' % i)
             cards = [
-                tag for tag in r.html.findAll('input')
+                tag for tag in r.html.find_all('input')
                 if (
                     tag.get('type') == 'hidden' and
                     tag.get('name') and
@@ -625,7 +625,7 @@ def test_subproject_permissions(self):
                 'new.mount_point': 'test-subproject',
                 'new.mount_label': 'Test Subproject'})
         r = self.app.get('/test-subproject/admin/permissions/')
-        assert len(r.html.findAll('input', {'name': 'card-0.value'})) == 0
+        assert len(r.html.find_all('input', {'name': 'card-0.value'})) == 0
         select = r.html.find('select', {'name': 'card-0.new'})
         opt_admin = select.find(string='Admin').parent
         opt_developer = select.find(string='Developer').parent
@@ -638,22 +638,22 @@ def test_subproject_permissions(self):
                 'card-0.id': 'admin'})
         r = self.app.get('/test-subproject/admin/permissions/')
         assigned_ids = [t['value']
-                        for t in r.html.findAll('input', {'name': 
'card-0.value'})]
+                        for t in r.html.find_all('input', {'name': 
'card-0.value'})]
         assert len(assigned_ids) == 2
         assert opt_developer['value'] in assigned_ids
         assert opt_admin['value'] in assigned_ids
 
     def test_project_groups(self):
         r = self.app.get('/admin/groups/')
-        dev_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[2]
+        dev_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[2]
         developer_id = dev_holder['data-group']
         with audits('add user test-user to Developer'):
             r = self.app.post('/admin/groups/add_user', params={
                 'role_id': developer_id,
                 'username': 'test-user'})
         r = self.app.get('/admin/groups/')
-        dev_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[2]
-        users = dev_holder.find('ul', {'class': 'users'}).findAll(
+        dev_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[2]
+        users = dev_holder.find('ul', {'class': 'users'}).find_all(
             'li', {'class': 'deleter'})
         assert 'test-user' in users[0]['data-user']
 
@@ -661,7 +661,7 @@ def test_new_admin_subscriptions(self):
         """Newly added admin must be subscribed to all the tools in the 
project"""
         r = self.app.get('/admin/groups/')
         admin_holder = r.html.find(
-            'table', {'id': 'usergroup_admin'}).findAll('tr')[1]
+            'table', {'id': 'usergroup_admin'}).find_all('tr')[1]
         admin_id = admin_holder['data-group']
         with audits('add user test-user to Admin'):
             self.app.post('/admin/groups/add_user', params={
@@ -691,7 +691,7 @@ def test_new_user_subscriptions(self):
         """Newly added user must not be subscribed to all the tools in the 
project if he is not admin"""
         r = self.app.get('/admin/groups/')
         dev_holder = r.html.find(
-            'table', {'id': 'usergroup_admin'}).findAll('tr')[2]
+            'table', {'id': 'usergroup_admin'}).find_all('tr')[2]
         developer_id = dev_holder['data-group']
         with audits('add user test-user to Developer'):
             self.app.post('/admin/groups/add_user', params={
@@ -709,16 +709,16 @@ def test_subroles(self):
         """Make sure subroles are preserved during group updates."""
         def check_roles(r):
             dev_holder = r.html.find(
-                'table', {'id': 'usergroup_admin'}).findAll('tr')[2]
+                'table', {'id': 'usergroup_admin'}).find_all('tr')[2]
             mem_holder = r.html.find(
-                'table', {'id': 'usergroup_admin'}).findAll('tr')[3]
+                'table', {'id': 'usergroup_admin'}).find_all('tr')[3]
             assert 'All users in Admin group' in dev_holder.text
             assert 'All users in Developer group' in mem_holder.text
 
         r = self.app.get('/admin/groups/')
 
         admin_holder = r.html.find(
-            'table', {'id': 'usergroup_admin'}).findAll('tr')[1]
+            'table', {'id': 'usergroup_admin'}).find_all('tr')[1]
         admin_id = admin_holder['data-group']
         # test that subroles are intact after user added
         with audits('add user test-user to Admin'):
@@ -740,9 +740,9 @@ def test_cannot_remove_all_admins(self):
         doesn't count)."""
         r = self.app.get('/admin/groups/')
         admin_holder = r.html.find(
-            'table', {'id': 'usergroup_admin'}).findAll('tr')[1]
+            'table', {'id': 'usergroup_admin'}).find_all('tr')[1]
         admin_id = admin_holder['data-group']
-        users = admin_holder.find('ul', {'class': 'users'}).findAll(
+        users = admin_holder.find('ul', {'class': 'users'}).find_all(
             'li', {'class': 'deleter'})
         assert len(users) == 1
         r = self.app.post('/admin/groups/remove_user', params={
@@ -752,15 +752,15 @@ def test_cannot_remove_all_admins(self):
             'error'] == 'You must have at least one user with the Admin role.'
         r = self.app.get('/admin/groups/')
         admin_holder = r.html.find(
-            'table', {'id': 'usergroup_admin'}).findAll('tr')[1]
-        users = admin_holder.find('ul', {'class': 'users'}).findAll(
+            'table', {'id': 'usergroup_admin'}).find_all('tr')[1]
+        users = admin_holder.find('ul', {'class': 'users'}).find_all(
             'li', {'class': 'deleter'})
         assert len(users) == 1
 
     def test_cannot_add_anon_to_group(self):
         r = self.app.get('/admin/groups/')
         dev_holder = r.html.find(
-            'table', {'id': 'usergroup_admin'}).findAll('tr')[2]
+            'table', {'id': 'usergroup_admin'}).find_all('tr')[2]
         developer_id = dev_holder['data-group']
         r = self.app.post('/admin/groups/add_user', params={
             'role_id': developer_id,
@@ -768,8 +768,8 @@ def test_cannot_add_anon_to_group(self):
         assert r.json['error'] == 'You must choose a user to add.'
         r = self.app.get('/admin/groups/')
         dev_holder = r.html.find(
-            'table', {'id': 'usergroup_admin'}).findAll('tr')[2]
-        users = dev_holder.find('ul', {'class': 'users'}).findAll(
+            'table', {'id': 'usergroup_admin'}).find_all('tr')[2]
+        users = dev_holder.find('ul', {'class': 'users'}).find_all(
             'li', {'class': 'deleter'})
         # no user was added
         assert len(users) == 0
@@ -779,7 +779,7 @@ def test_cannot_add_anon_to_group(self):
 
     def test_project_multi_groups(self):
         r = self.app.get('/admin/groups/')
-        admin_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[1]
+        admin_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[1]
         admin_id = admin_holder['data-group']
         with audits('add user test-user to Admin'):
             r = self.app.post('/admin/groups/add_user', params={
@@ -810,12 +810,12 @@ def test_new_group(self):
             r = self.app.post('/admin/groups/create',
                               params={'name': 'RoleNew1'})
         r = self.app.get('/admin/groups/')
-        role_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[4]
+        role_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[4]
         assert 'RoleNew1' in role_holder.text
         role_id = role_holder['data-group']
 
         # add test-user to role
-        role_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[4]
+        role_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[4]
         with audits('add user test-user to RoleNew1'):
             r = self.app.post('/admin/groups/add_user', params={
                 'role_id': role_id,
@@ -826,7 +826,7 @@ def test_new_group(self):
                 'group_name': 'RoleNew1'})
         assert 'deleted' in self.webflash(r)
         r = self.app.get('/admin/groups/', status=200)
-        roles = [t.text for t in r.html.findAll('td', {'class': 'group'})]
+        roles = [t.text for t in r.html.find_all('td', {'class': 'group'})]
         assert 'RoleNew1' not in roles
 
         # make sure can still access homepage after one of user's roles were
@@ -837,8 +837,8 @@ def test_new_group(self):
 
     def test_change_perms(self):
         r = self.app.get('/admin/groups/')
-        dev_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[2]
-        mem_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[3]
+        dev_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[2]
+        mem_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[3]
         mem_id = mem_holder['data-group']
         # neither group has create permission
         assert dev_holder.select_one('li[data-permission=create]')['class'] == 
["no"]
@@ -849,8 +849,8 @@ def test_change_perms(self):
             'permission': 'create',
             'allow': 'true'})
         r = self.app.get('/admin/groups/')
-        dev_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[2]
-        mem_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[3]
+        dev_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[2]
+        mem_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[3]
         # Member now has create permission
         assert mem_holder.select_one('li[data-permission=create]')['class'] == 
["yes"]
         # Developer has inherited create permission from Member
@@ -861,19 +861,19 @@ def test_change_perms(self):
             'permission': 'create',
             'allow': 'false'})
         r = self.app.get('/admin/groups/')
-        dev_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[2]
-        mem_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[3]
+        dev_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[2]
+        mem_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[3]
         # neither group has create permission
         assert dev_holder.select_one('li[data-permission=create]')['class'] == 
["no"]
         assert mem_holder.select_one('li[data-permission=create]')['class'] == 
["no"]
 
     def test_permission_inherit(self):
         r = self.app.get('/admin/groups/')
-        admin_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[1]
+        admin_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[1]
         admin_id = admin_holder['data-group']
-        mem_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[3]
+        mem_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[3]
         mem_id = mem_holder['data-group']
-        anon_holder = r.html.find('table', {'id': 
'usergroup_admin'}).findAll('tr')[5]
+        anon_holder = r.html.find('table', {'id': 
'usergroup_admin'}).find_all('tr')[5]
         anon_id = anon_holder['data-group']
         # first remove create from Admin so we can see it inherit
         r = self.app.post('/admin/groups/change_perm', params={
@@ -1010,10 +1010,10 @@ def test_project_perms_display(self):
         neighborhood = M.Neighborhood.query.get(name='Projects')
         neighborhood.features['private_projects'] = False
         r = self.app.get('/admin/groups/')
-        groups = r.html.find('table', {'id': 
'usergroup_admin'}).select_one('tbody').findAll('tr')[:-1]
+        groups = r.html.find('table', {'id': 
'usergroup_admin'}).select_one('tbody').find_all('tr')[:-1]
         for gr in groups:
             group_name = gr.select_one('td').text.strip()
-            group_perms = gr.find('ul', {'class': 'permissions'}).findAll('li')
+            group_perms = gr.find('ul', {'class': 
'permissions'}).find_all('li')
             if group_name in ['Authenticated', 'Anonymous']:
                 assert len(group_perms) == 0
             else:
@@ -1024,10 +1024,10 @@ def test_private_projects_perms(self):
         neighborhood = M.Neighborhood.query.get(name='Projects')
         neighborhood.features['private_projects'] = True
         r = self.app.get('/admin/groups/')
-        groups = r.html.find('table', {'id': 
'usergroup_admin'}).select_one('tbody').findAll('tr')[:-1]
+        groups = r.html.find('table', {'id': 
'usergroup_admin'}).select_one('tbody').find_all('tr')[:-1]
         for gr in groups:
             group_name = gr.select_one('td').text.strip()
-            group_perms = gr.find('ul', {'class': 'permissions'}).findAll('li')
+            group_perms = gr.find('ul', {'class': 
'permissions'}).find_all('li')
             if group_name not in ['Authenticated', 'Anonymous']:
                 assert len(group_perms) == 4  # read permission is being 
displayed
             else:
diff --git a/Allura/allura/tests/functional/test_auth.py 
b/Allura/allura/tests/functional/test_auth.py
index 2f6a76af4..f5a88ce1f 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -271,13 +271,13 @@ def test_logout(self):
             antispam=True).follow().follow()
 
         logged_in_session = r.session['_id']
-        links = r.html.find(*nav_pattern).findAll('a')
+        links = r.html.find(*nav_pattern).find_all('a')
         assert links[-1].string == "Log Out"
 
         r = self.app.get('/auth/logout').follow().follow()
         logged_out_session = r.session['_id']
         assert logged_in_session is not logged_out_session
-        links = r.html.find(*nav_pattern).findAll('a')
+        links = r.html.find(*nav_pattern).find_all('a')
         assert links[-1].string == 'Log In'
 
     def test_track_login(self):
@@ -1773,7 +1773,7 @@ def test_password_reset(self, gen_message_id, 
sendsimplemail):
             r = form.submit()
         print(r)
         if r.status == 200:
-            assert [] == r.html.findAll(attrs={'class': 'fielderror'})
+            assert [] == r.html.find_all(attrs={'class': 'fielderror'})
         assert 'Your old and new password should not be the same' in 
self.webflash(r)
         r = r.follow()
 
diff --git a/Allura/allura/tests/functional/test_discuss.py 
b/Allura/allura/tests/functional/test_discuss.py
index 13935414b..e3d05e85e 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -42,11 +42,11 @@ def _thread_id(self):
     def _make_post(self, text, username='root'):
         thread_link = self._thread_link()
         thread = self.app.get(thread_link, expect_errors=True)
-        for f in thread.html.findAll('form'):
+        for f in thread.html.find_all('form'):
             if f.get('action', '').endswith('/post'):
                 break
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -96,7 +96,7 @@ def test_post(self, submit_spam, check_spam):
         r = self.app.get(post_link)
         post_form = r.html.find('form', {'action': post_link})
         params = dict()
-        inputs = post_form.findAll('input')
+        inputs = post_form.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -110,7 +110,7 @@ def test_post(self, submit_spam, check_spam):
         assert str(r).count('This is a new post') == 3
         post_form = r.html.find('form', {'action': post_link + 'reply'})
         params = dict()
-        inputs = post_form.findAll('input')
+        inputs = post_form.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -121,7 +121,7 @@ def test_post(self, submit_spam, check_spam):
         r = self.app.get(thread_link)
         assert 'Tis a reply' in r, r
         permalinks = [post.find('form')['action']
-                      for post in r.html.findAll('div', {'class': 
'edit_post_form reply'})]
+                      for post in r.html.find_all('div', {'class': 
'edit_post_form reply'})]
         self.app.post(permalinks[1] + 'flag')
         self.app.post(permalinks[1] + 'moderate', params=dict(delete='delete'))
         self.app.post(permalinks[0] + 'moderate', params=dict(spam='spam'))
@@ -298,7 +298,7 @@ def test_user_filter(self):
             params=dict(
                 status=post.status
             ))
-        assert r_no_filtered.html.tbody.findAll('tr') != []
+        assert r_no_filtered.html.tbody.find_all('tr') != []
 
         # filter with existing user
         r_filtered = self.app.get(
@@ -307,8 +307,8 @@ def test_user_filter(self):
                 username=post_username,
                 status=post.status
             ))
-        assert r_filtered.html.tbody.findAll('tr') != []
-        assert post_username in r_filtered.html.tbody.findAll('td')[-5].string
+        assert r_filtered.html.tbody.find_all('tr') != []
+        assert post_username in r_filtered.html.tbody.find_all('td')[-5].string
 
         # filter without existing user
         r_bad_filtered = self.app.get(
@@ -317,7 +317,7 @@ def test_user_filter(self):
                 username='bad_filtered_user',
                 status=post.status
             ))
-        assert r_bad_filtered.html.tbody.findAll('tr') == []
+        assert r_bad_filtered.html.tbody.find_all('tr') == []
 
     def test_undo(self):
         r = self._make_post('Test post')
@@ -369,7 +369,7 @@ def test_edit_post(self, create_activity):
         assert 'This is a post' in r.html.find('div', {'class': 
'display_post'}).text
         assert 'Last edit:' not in r.html.find('div', {'class': 
'display_post'}).text
         params = dict()
-        inputs = reply_form.findAll('input')
+        inputs = reply_form.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -400,12 +400,12 @@ def setup_method(self, method):
         super().setup_method(method)
         self.thread_link = self._thread_link()
         thread = self.app.get(self.thread_link, status=404)
-        for f in thread.html.findAll('form'):
+        for f in thread.html.find_all('form'):
             if f.get('action', '').endswith('/post'):
                 break
         self.post_form_link = f['action']
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -418,7 +418,7 @@ def setup_method(self, method):
 
     def attach_link(self):
         r = self.app.get(self.thread_link)
-        for alink in r.html.findAll('a'):
+        for alink in r.html.find_all('a'):
             if 'attachment' in alink['href']:
                 alink = str(alink['href'])
                 return alink
@@ -460,7 +460,7 @@ def test_reply_attach(self, notify):
         r = self.app.get(self.thread_link)
         post_form = r.html.find('form', {'action': self.post_link + 'reply'})
         params = dict()
-        inputs = post_form.findAll('input')
+        inputs = post_form.find_all('input')
 
         for field in inputs:
             if field.has_attr('name') and field['name'] != 'file_info':
diff --git a/Allura/allura/tests/functional/test_home.py 
b/Allura/allura/tests/functional/test_home.py
index 24601cd3e..b98c5ba7d 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -36,7 +36,7 @@ def test_project_nav(self):
         root = self.app.get('/p/test/wiki/').follow()
         assert re.search(r'<!-- Server: \S+ -->',
                          str(root.html)), 'Missing Server comment'
-        nav_links = root.html.find('div', dict(id='top_nav')).findAll('a')
+        nav_links = root.html.find('div', dict(id='top_nav')).find_all('a')
         nav_links = [nl for nl in nav_links if 'add-tool-toggle' not in 
nl['class']]
         assert len(nav_links) == len(response.json['menu'])
         for nl, entry in zip(nav_links, response.json['menu']):
@@ -208,7 +208,7 @@ def test_members(self):
         assert '<td>Test Admin</td>' in r
         assert '<td><a href="/u/test-admin/profile/">test-admin</a></td>' in r
         assert '<td>Admin</td>' in r
-        tr = r.html.findAll('tr')
+        tr = r.html.find_all('tr')
         assert "<td>Test Admin</td>" in str(tr[1])
         assert "<td>Test User 2</td>" in str(tr[2])
         assert "<td>Test User</td>" in str(tr[3])
@@ -242,7 +242,7 @@ def test_toolaccess_before_subproject(self):
         # Install and Verify a Tool in the subproject.
         pr.install_app(ep_name='Wiki', mount_point='test-sub', 
mount_label='Test Sub', ordinal='1')
         r = self.app.get('/p/test/test-mount/test-sub/').follow()
-        active_link = r.html.findAll('li', {'class': 'selected'})
+        active_link = r.html.find_all('li', {'class': 'selected'})
         assert len(active_link) == 1
         assert active_link[0].contents[1]['href'] == 
'/p/test/test-mount/test-sub/'
         assert 'Welcome to your wiki!' in r
@@ -267,7 +267,7 @@ def test_toolaccess_before_subproject(self):
 
         # Check if the tool is accessed and not the subproject.
         r = self.app.get('/p/test/test-mount/').follow()
-        active_link = r.html.findAll('li', {'class': 'selected'})
+        active_link = r.html.find_all('li', {'class': 'selected'})
         assert len(active_link) == 1
         assert active_link[0].contents[1]['href'] == '/p/test/test-mount/'
         assert 'Welcome to your wiki!' in r
diff --git a/Allura/allura/tests/functional/test_nav.py 
b/Allura/allura/tests/functional/test_nav.py
index 376fad571..fc40180b9 100644
--- a/Allura/allura/tests/functional/test_nav.py
+++ b/Allura/allura/tests/functional/test_nav.py
@@ -57,7 +57,7 @@ def test_global_nav_links_present(self):
         with h.push_config(config, **self._set_config()):
             response = self.app.get('/').follow()
         nav_left = response.html.find(*self.global_nav_pattern)
-        assert len(nav_left.findAll('a')) == 1
+        assert len(nav_left.find_all('a')) == 1
         assert nav_left.a.get('href') == self.nav_data['url']
         assert nav_left.a.text == self.nav_data['title']
 
@@ -66,13 +66,13 @@ def test_global_nav_links_absent(self, global_nav):
         with h.push_config(config, **self._set_config()):
             response = self.app.get('/').follow()
         nav_left = response.html.find(*self.global_nav_pattern)
-        assert len(nav_left.findAll('a')) == 0
+        assert len(nav_left.find_all('a')) == 0
 
     def test_logo_absent_if_not_image_path(self):
         with h.push_config(config, **self._set_config()):
             response = self.app.get('/').follow()
         nav_logo = response.html.find(*self.logo_pattern)
-        assert len(nav_logo.findAll('a')) == 0
+        assert len(nav_logo.find_all('a')) == 0
 
     def test_logo_present(self):
         self.logo_data = {
@@ -80,7 +80,7 @@ def test_logo_present(self):
         with h.push_config(config, **self._set_config()):
             response = self.app.get('/').follow()
         nav_logo = response.html.find(*self.logo_pattern)
-        assert len(nav_logo.findAll('a')) == 1
+        assert len(nav_logo.find_all('a')) == 1
         assert self.logo_data['path'] in nav_logo.a.img.get('src')
 
     def test_logo_no_redirect_url_set_default(self):
@@ -89,7 +89,7 @@ def test_logo_no_redirect_url_set_default(self):
         with h.push_config(config, **self._set_config()):
             response = self.app.get('/').follow()
         nav_logo = response.html.find(*self.logo_pattern)
-        assert len(nav_logo.findAll('a')) == 1
+        assert len(nav_logo.find_all('a')) == 1
         assert nav_logo.a.get('href') == '/'
 
     def test_logo_image_width_and_height(self):
diff --git a/Allura/allura/tests/functional/test_personal_dashboard.py 
b/Allura/allura/tests/functional/test_personal_dashboard.py
index 68d64392d..9cf00b03a 100644
--- a/Allura/allura/tests/functional/test_personal_dashboard.py
+++ b/Allura/allura/tests/functional/test_personal_dashboard.py
@@ -36,7 +36,7 @@ class TestPersonalDashboard(TestController):
     def test_dashboard(self):
         r = self.app.get('/dashboard')
         assert 'Test Admin / Dashboard' == r.html.find('h1', 
'project_title').text.strip()
-        sections = {c for s in r.html.findAll(None, 'profile-section') for c 
in s['class']}
+        sections = {c for s in r.html.find_all(None, 'profile-section') for c 
in s['class']}
         assert 'tickets' in sections
         assert 'projects' in sections
         assert 'merge_requests' in sections
diff --git a/Allura/allura/tests/functional/test_root.py 
b/Allura/allura/tests/functional/test_root.py
index 8c86769e7..e3297edea 100644
--- a/Allura/allura/tests/functional/test_root.py
+++ b/Allura/allura/tests/functional/test_root.py
@@ -82,9 +82,9 @@ def test_neighborhood(self):
         response = self.app.get('/neighborhood')
         assert response.html.find('h2', {'class': 'dark 
title'}).find('span').contents[
             0].strip() == 'All Neighborhoods'
-        nbhds = response.html.findAll('div', {'class': 'nbhd_name'})
+        nbhds = response.html.find_all('div', {'class': 'nbhd_name'})
         assert nbhds[0].find('a').get('href') == '/adobe/'
-        cat_links = response.html.find('div', {'id': 'sidebar'}).findAll('li')
+        cat_links = response.html.find('div', {'id': 'sidebar'}).find_all('li')
         assert len(cat_links) == 4
         assert cat_links[0].find('a').get('href') == '/browse/clustering'
         assert cat_links[0].find('a').find('span').string == 'Clustering'
@@ -130,19 +130,19 @@ def test_project_browse(self):
                              ).first().category_id = com_cat._id
         response = self.app.get('/browse')
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-1/'})) == 1
+            response.html.find_all('a', {'href': '/adobe/adobe-1/'})) == 1
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-2/'})) == 1
+            response.html.find_all('a', {'href': '/adobe/adobe-2/'})) == 1
         response = self.app.get('/browse/communications')
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-1/'})) == 1
+            response.html.find_all('a', {'href': '/adobe/adobe-1/'})) == 1
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-2/'})) == 0
+            response.html.find_all('a', {'href': '/adobe/adobe-2/'})) == 0
         response = self.app.get('/browse/communications/fax')
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-1/'})) == 0
+            response.html.find_all('a', {'href': '/adobe/adobe-1/'})) == 0
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-2/'})) == 0
+            response.html.find_all('a', {'href': '/adobe/adobe-2/'})) == 0
 
     def test_neighborhood_home(self):
         setup_trove_categories()
@@ -153,9 +153,9 @@ def test_neighborhood_home(self):
             p.install_app('home', 'home', 'Home', ordinal=0)
 
         response = self.app.get('/adobe/')
-        projects = response.html.findAll('div', {'class': 'list card 
proj_icon'})
+        projects = response.html.find_all('div', {'class': 'list card 
proj_icon'})
         assert len(projects) == 2
-        cat_links = response.html.find('div', {'id': 
'sidebar'}).findAll('ul')[1].findAll('li')
+        cat_links = response.html.find('div', {'id': 
'sidebar'}).find_all('ul')[1].find_all('li')
         assert len(cat_links) == 3, cat_links
         assert cat_links[0].find('a').get('href') == '/adobe/browse/clustering'
         assert cat_links[0].find('a').find('span').string == 'Clustering'
@@ -170,19 +170,19 @@ def test_neighborhood_project_browse(self):
                              ).first().category_id = fax_cat._id
         response = self.app.get('/adobe/browse')
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-1/'})) == 1
+            response.html.find_all('a', {'href': '/adobe/adobe-1/'})) == 1
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-2/'})) == 1
+            response.html.find_all('a', {'href': '/adobe/adobe-2/'})) == 1
         response = self.app.get('/adobe/browse/communications')
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-1/'})) == 1
+            response.html.find_all('a', {'href': '/adobe/adobe-1/'})) == 1
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-2/'})) == 1
+            response.html.find_all('a', {'href': '/adobe/adobe-2/'})) == 1
         response = self.app.get('/adobe/browse/communications/fax')
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-1/'})) == 0
+            response.html.find_all('a', {'href': '/adobe/adobe-1/'})) == 0
         assert len(
-            response.html.findAll('a', {'href': '/adobe/adobe-2/'})) == 1
+            response.html.find_all('a', {'href': '/adobe/adobe-2/'})) == 1
 
     def test_slash_redirect(self):
         self.app.get('/p', status=301)
diff --git a/Allura/allura/tests/functional/test_site_admin.py 
b/Allura/allura/tests/functional/test_site_admin.py
index a6e955072..d9767e8fd 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -53,7 +53,7 @@ def test_stats(self):
         assert 'Forge Site Admin' in r.html.find(
             'h2', {'class': 'dark title'}).find('span').contents[0]
         stats_table = r.html.find('table')
-        cells = stats_table.findAll('td')
+        cells = stats_table.find_all('td')
         assert cells[0].contents[0] == 'Adobe', cells[0].contents[0]
 
     def test_tickets_access(self):
@@ -71,7 +71,7 @@ def test_new_projects_access(self):
     def test_new_projects(self):
         r = self.app.get('/nf/admin/new_projects', extra_environ=dict(
             username='root'))
-        headers = r.html.find('table').findAll('th')
+        headers = r.html.find('table').find_all('th')
         assert headers[1].contents[0] == 'Created'
         assert headers[2].contents[0] == 'Shortname'
         assert headers[3].contents[0] == 'Name'
@@ -84,25 +84,25 @@ def test_new_projects_deleted_projects(self):
         '''Deleted projects should not be visible here'''
         r = self.app.get('/nf/admin/new_projects', extra_environ=dict(
             username='root'))
-        count = len(r.html.find('table').findAll('tr'))
+        count = len(r.html.find('table').find_all('tr'))
         p = M.Project.query.get(shortname='test')
         p.deleted = True
         ThreadLocalODMSession.flush_all()
         r = self.app.get('/nf/admin/new_projects', extra_environ=dict(
             username='root'))
-        assert len(r.html.find('table').findAll('tr')) == count - 1
+        assert len(r.html.find('table').find_all('tr')) == count - 1
 
     def test_new_projects_daterange_filtering(self):
         r = self.app.get('/nf/admin/new_projects', extra_environ=dict(
             username='root'))
-        count = len(r.html.find('table').findAll('tr'))
+        count = len(r.html.find('table').find_all('tr'))
         assert count == 7
 
         filtr = r.forms[0]
         filtr['start-dt'] = '2000/01/01 10:10:10'
         filtr['end-dt'] = '2000/01/01 09:09:09'
         r = filtr.submit()
-        count = len(r.html.find('table').findAll('tr'))
+        count = len(r.html.find('table').find_all('tr'))
         assert count == 1  # only row with headers - no results
 
     def test_reclone_repo_access(self):
@@ -204,8 +204,8 @@ def test_site_notifications(self):
         r = self.app.get('/nf/admin/site_notifications/', extra_environ=dict(
             username='root'))
         table = r.html.find('table')
-        headers = table.findAll('th')
-        row = table.findAll('td')
+        headers = table.find_all('th')
+        row = table.find_all('td')
 
         assert headers[0].contents[0] == 'Active'
         assert headers[1].contents[0] == 'Impressions'
@@ -372,9 +372,9 @@ def setup_method(self, method):
     def test_default_fields(self, search):
         search.site_admin_search.return_value = self.TEST_HIT
         r = self.app.get('/nf/admin/search_projects?q=fake&f=shortname')
-        options = [o['value'] for o in r.html.findAll('option')]
+        options = [o['value'] for o in r.html.find_all('option')]
         assert options == ['shortname', 'name', '__custom__']
-        ths = [th.text for th in r.html.findAll('th')]
+        ths = [th.text for th in r.html.find_all('th')]
         assert ths == ['Short name', 'Full name', 'Registered', 'Deleted?', 
'Details']
 
     @patch('allura.controllers.site_admin.search')
@@ -383,9 +383,9 @@ def test_additional_fields(self, search):
         with h.push_config(config, 
**{'search.project.additional_search_fields': 'private, url',
                                       
'search.project.additional_display_fields': 'url'}):
             r = self.app.get('/nf/admin/search_projects?q=fake&f=shortname')
-        options = [o['value'] for o in r.html.findAll('option')]
+        options = [o['value'] for o in r.html.find_all('option')]
         assert options == ['shortname', 'name', 'private', 'url', '__custom__']
-        ths = [th.text for th in r.html.findAll('th')]
+        ths = [th.text for th in r.html.find_all('th')]
         assert ths == ['Short name', 'Full name', 'Registered', 'Deleted?', 
'url', 'Details']
 
 
@@ -425,9 +425,9 @@ def setup_method(self, method):
     def test_default_fields(self, site_admin_search):
         site_admin_search.return_value = self.TEST_HIT
         r = self.app.get('/nf/admin/search_users?q=fake&f=username')
-        options = [o['value'] for o in r.html.findAll('option')]
+        options = [o['value'] for o in r.html.find_all('option')]
         assert options == ['username', 'display_name', '__custom__']
-        ths = [th.text for th in r.html.findAll('th')]
+        ths = [th.text for th in r.html.find_all('th')]
         assert ths == ['Username', 'Display name', 'Email', 'Registered',
                        'Status', 'Details']
 
@@ -437,9 +437,9 @@ def test_additional_fields(self, site_admin_search):
         with h.push_config(config, **{'search.user.additional_search_fields': 
'email_addresses, url',
                                       'search.user.additional_display_fields': 
'url'}):
             r = self.app.get('/nf/admin/search_users?q=fake&f=username')
-        options = [o['value'] for o in r.html.findAll('option')]
+        options = [o['value'] for o in r.html.find_all('option')]
         assert options == ['username', 'display_name', 'email_addresses', 
'url', '__custom__']
-        ths = [th.text for th in r.html.findAll('th')]
+        ths = [th.text for th in r.html.find_all('th')]
         assert ths == ['Username', 'Display name', 'Email', 'Registered',
                        'Status', 'url', 'Details']
 
@@ -471,8 +471,8 @@ def test_general_info(self):
         assert 'IP: 7.7.7.7' in r
         assert 'UA: browser of the future 1.1' in r
         # list of projects
-        projects = r.html.findAll('fieldset')[-1]
-        projects = [e.getText() for e in projects.findAll('li')]
+        projects = r.html.find_all('fieldset')[-1]
+        projects = [e.getText() for e in projects.find_all('li')]
         assert 'Test 2\n\u2013\nAdmin\n' in projects
         assert 'Test Project\n\u2013\nAdmin\n' in projects
         assert 'Adobe project 1\n\u2013\nAdmin\n' in projects
@@ -770,7 +770,7 @@ def test_confirm_step_values(self):
             assert confirm_form[f].value == form[f].value
         assert confirm_form['projects'].value == 'p/test    # OK: 
/p/test/\ndne/dne    # Neighborhood not found'
 
-        confirm_data = r.html.find('table').findAll('td')
+        confirm_data = r.html.find('table').find_all('td')
         assert len(confirm_data) == 4  # 2 projects == 2 rows (2 columns each)
         assert confirm_data[0].getText() == 'p/test'
         assert confirm_data[1].find('a').get('href') == '/p/test/'
@@ -787,7 +787,7 @@ def test_confirm_step_edit_link(self):
         r = form.submit()
         expected_href = 
'./?projects=p/test++++%23+OK:+/p/test%0Ap/dne++++%23+Project not found'
         expected_href += '&reason=The+Reason%0AMultiline&disable_users=True'
-        assert r.html.findAll('a', {'href': expected_href}) is not None
+        assert r.html.find_all('a', {'href': expected_href}) is not None
 
     @patch('allura.controllers.site_admin.DeleteProjects', autospec=True)
     def test_reason_passed_to_task(self, dp):
diff --git a/Allura/allura/tests/functional/test_user_profile.py 
b/Allura/allura/tests/functional/test_user_profile.py
index 230bafb95..2e9cc7af3 100644
--- a/Allura/allura/tests/functional/test_user_profile.py
+++ b/Allura/allura/tests/functional/test_user_profile.py
@@ -71,7 +71,7 @@ def test_profile(self):
         r = self.app.get('/u/test-admin/profile/')
         assert ('Test Admin' ==
                 r.html.find('h1', 'project_title').find('a').text)
-        sections = {c for s in r.html.findAll(None, 'profile-section') for c 
in s['class']}
+        sections = {c for s in r.html.find_all(None, 'profile-section') for c 
in s['class']}
         assert 'personal-data' in sections
         assert 'Username:\ntest-admin' in r.html.find(None, 
'personal-data').getText().replace(' ', '')
         assert 'projects' in sections
diff --git a/Allura/allura/tests/test_webhooks.py 
b/Allura/allura/tests/test_webhooks.py
index d0bbd83e2..d4460fb5e 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -374,7 +374,7 @@ def test_list_webhooks(self):
 
         r = self.app.get(self.url)
         assert '<h1>repo-push</h1>' in r
-        rows = r.html.find('table').findAll('tr')
+        rows = r.html.find('table').find_all('tr')
         assert len(rows) == 2
         rows = sorted((self._format_row(row) for row in rows), key=lambda 
rows: rows[0]['text'])
         expected_rows = sorted([
@@ -408,7 +408,7 @@ def delete_btn(td):
             a = td.find('a')
             return {'href': a.get('href'), 'data-id': a.get('data-id')}
 
-        tds = row.findAll('td')
+        tds = row.find_all('td')
         return [text(tds[0]), text(tds[1]), link(tds[2]), delete_btn(tds[3])]
 
 
diff --git a/AlluraTest/alluratest/controller.py 
b/AlluraTest/alluratest/controller.py
index b41d69dfe..1ffba920d 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -198,7 +198,7 @@ def subscription_options(self, response):
         component from the <script> tag
         """
         script = None
-        for s in response.html.findAll('script'):
+        for s in response.html.find_all('script'):
             if s.getText().strip().startswith('document.SUBSCRIPTION_OPTIONS'):
                 script = s
                 break
diff --git a/ForgeActivity/forgeactivity/tests/functional/test_root.py 
b/ForgeActivity/forgeactivity/tests/functional/test_root.py
index 8b8443e89..621e7365d 100644
--- a/ForgeActivity/forgeactivity/tests/functional/test_root.py
+++ b/ForgeActivity/forgeactivity/tests/functional/test_root.py
@@ -94,7 +94,7 @@ def test_index_html(self, director):
         })]
         r = self.app.get('/p/test/activity/')
         timeline = r.html.find('ul', 'timeline')
-        assert 1 == len(timeline.findAll('li'))
+        assert 1 == len(timeline.find_all('li'))
         activity = timeline.find('li')
         assert activity.time['title'] == "2013-12-04 21:48:19"
         h1 = """\
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py 
b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
index 7dd22f0b1..b586e7f72 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
@@ -84,8 +84,8 @@ def test_html_email(self):
             msg)
         r = self.app.get('/p/test/discussion/testforum/')
         assert 'Test Simple Thread' in str(r), r
-        assert len(r.html.findAll('tr')) == 2
-        href = r.html.findAll('tr')[1].find('a')['href']
+        assert len(r.html.find_all('tr')) == 2
+        href = r.html.find_all('tr')[1].find('a')['href']
         r = self.app.get(href)
         assert 'alternate' in str(r)
 
@@ -116,8 +116,8 @@ def test_html_email_with_images(self):
             msg)
         r = self.app.get('/p/test/discussion/testforum/')
         assert 'Test Simple Thread' in str(r)
-        assert len(r.html.findAll('tr')) == 2
-        href = r.html.findAll('tr')[1].find('a')['href']
+        assert len(r.html.find_all('tr')) == 2
+        href = r.html.find_all('tr')[1].find('a')['href']
         r = self.app.get(href)
         assert 'alternate' in str(r)
         assert 'python-logo.png' in str(r)
@@ -244,7 +244,7 @@ def test_posts(self):
         r = self.app.get(url)
         f = r.html.find('form', {'action': '/p/test' + url})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -255,7 +255,7 @@ def test_posts(self):
         r = self.app.get(url, params=dict(version='1'))
         post_form = r.html.find('form', {'action': '/p/test' + url + 'reply'})
         params = dict()
-        inputs = post_form.findAll('input')
+        inputs = post_form.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -278,7 +278,7 @@ def test_posts(self):
         r = self.app.get(url)
         assert "test1.txt" in r
         assert "test2.txt" in r
-        for link in r.html.findAll('a.btn'):
+        for link in r.html.find_all('a.btn'):
             if 'attachment' in link.get('href', ''):
                 self.app.get(str(link['href']))
                 self.app.post(str(link['href']), params=dict(delete='on'))
@@ -372,7 +372,7 @@ def test_markdown_description(self):
         form['add_forum.description'] = '<a href="http://cnn.com";>This is 
CNN</a>'
         form.submit()
         r = self.app.get('/discussion/')
-        assert len(r.html.findAll('a', rel='nofollow')) == 2
+        assert len(r.html.find_all('a', rel='nofollow')) == 2
 
     def test_forum_search(self):
         self.app.get('/discussion/search')
@@ -396,7 +396,7 @@ def _post_pending():
             f = r.html.find(
                 'form', {'action': '/p/test/discussion/save_new_topic'})
             params = dict()
-            inputs = f.findAll('input')
+            inputs = f.find_all('input')
             for field in inputs:
                 if field.has_attr('name'):
                     params[field['name']] = field.get('value') or ''
@@ -455,7 +455,7 @@ def test_save_moderation_bulk_user(self):
             f = r.html.find(
                 'form', {'action': '/p/test/discussion/save_new_topic'})
             params = dict()
-            inputs = f.findAll('input')
+            inputs = f.find_all('input')
             for field in inputs:
                 if field.has_attr('name'):
                     params[field['name']] = field.get('value') or ''
@@ -476,7 +476,7 @@ def test_posting(self):
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': 
'/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -509,7 +509,7 @@ def test_notifications_escaping(self):
         f = r.html.find(
             'form', {'action': '/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -544,7 +544,7 @@ def test_anonymous_post(self, spam_checker):
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': 
'/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -569,7 +569,7 @@ def test_anonymous_post(self, spam_checker):
         f = r.html.find('div', {'class': 'comment-row 
reply_post_form'}).find('form')
         rep_url = f.get('action')
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -637,7 +637,7 @@ def test_thread(self):
         f = r.html.find(
             'form', {'action': '/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -651,7 +651,7 @@ def test_thread(self):
         f = thread.html.find('div', {'class': 'comment-row 
reply_post_form'}).find('form')
         rep_url = f.get('action')
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -659,9 +659,9 @@ def test_thread(self):
         thread = self.app.post(str(rep_url), params=params)
         thread = self.app.get(url)
         # beautiful soup is getting some unicode error here - test without it
-        assert thread.html.findAll(
+        assert thread.html.find_all(
             'div', {'class': 'display_post'})[0].find('p').string == 'aaa'
-        assert thread.html.findAll(
+        assert thread.html.find_all(
             'div', {'class': 'display_post'})[1].find('p').string == 'bbb'
         assert thread.response.text.count(
             '<div class="comment-row reply_post_form') == 2
@@ -673,7 +673,7 @@ def test_thread(self):
         reply_form = r.html.find('div', {'class': 'edit_post_form 
reply'}).find('form')
         post_link = str(reply_form['action'])
         params = dict()
-        inputs = reply_form.findAll('input')
+        inputs = reply_form.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -687,7 +687,7 @@ def test_subscription_controls(self):
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': 
'/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -701,7 +701,7 @@ def test_subscription_controls(self):
         f = r.html.find('form', {'class': 'follow_form'})
         subscribe_url = f.get('action')
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -710,7 +710,7 @@ def test_subscription_controls(self):
         f = thread.html.find('div', {'class': 'comment-row 
reply_post_form'}).find('form')
         rep_url = f.get('action')
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -721,21 +721,21 @@ def test_subscription_controls(self):
 
     def get_table_rows(self, response, closest_id):
         tbody = response.html.find('div', {'id': closest_id}).find('tbody')
-        rows = tbody.findAll('tr')
+        rows = tbody.find_all('tr')
         return rows
 
     def check_announcement_table(self, response, topic_name):
         assert response.html.find(string='Announcements')
         rows = self.get_table_rows(response, 'announcements')
         assert len(rows) == 1
-        cell = rows[0].findAll('td', {'class': 'topic'})
+        cell = rows[0].find_all('td', {'class': 'topic'})
         assert topic_name in str(cell)
 
     def test_thread_announcement(self):
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': 
'/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -788,7 +788,7 @@ def test_thread_sticky(self):
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': 
'/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -802,7 +802,7 @@ def test_thread_sticky(self):
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': 
'/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -853,7 +853,7 @@ def test_move_thread(self):
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': 
'/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -868,7 +868,7 @@ def test_move_thread(self):
             'div', {'class': 'comment-row reply_post_form'}).find('form')
         rep_url = f.get('action')
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -876,7 +876,7 @@ def test_move_thread(self):
         thread = self.app.post(str(rep_url), params=params)
         thread = self.app.get(url)
         # make sure the posts are in the original thread
-        posts = thread.html.find('div', {'id': 'comment'}).findAll(
+        posts = thread.html.find('div', {'id': 'comment'}).find_all(
             'div', {'class': 'discussion-post'})
         assert len(posts) == 2
         # move the thread
@@ -884,7 +884,7 @@ def test_move_thread(self):
             flags='',
             discussion='general')).follow()
         # make sure all the posts got moved
-        posts = r.html.find('div', {'id': 'comment'}).findAll(
+        posts = r.html.find('div', {'id': 'comment'}).find_all(
             'div', {'class': 'discussion-post'})
         assert len(posts) == 2
 
@@ -893,7 +893,7 @@ def test_rename_thread(self):
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': 
'/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -923,7 +923,7 @@ def test_sidebar_menu(self):
         r = self.app.get('/discussion/')
         sidebar = r.html.find('div', {'id': 'sidebar'})
         sidebar_menu = str(sidebar)
-        sidebar_links = [i['href'] for i in sidebar.findAll('a')]
+        sidebar_links = [i['href'] for i in sidebar.find_all('a')]
         assert "/p/test/discussion/create_topic/" in sidebar_links
         assert "/p/test/discussion/new_forum" in sidebar_links
         assert '<h3 class="">Help</h3>' in sidebar_menu
@@ -932,7 +932,7 @@ def test_sidebar_menu(self):
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': 
'/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -947,7 +947,7 @@ def test_sidebar_menu_anon(self):
         r = self.app.get('/discussion/')
         sidebar = r.html.find('div', {'id': 'sidebar'})
         sidebar_menu = str(sidebar)
-        sidebar_links = [i['href'] for i in sidebar.findAll('a')]
+        sidebar_links = [i['href'] for i in sidebar.find_all('a')]
         assert "/p/test/discussion/create_topic/" in sidebar_links
         assert "/p/test/discussion/new_forum" in sidebar_links
         assert '<h3 class="">Help</h3>' in sidebar_menu
@@ -956,7 +956,7 @@ def test_sidebar_menu_anon(self):
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': 
'/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
diff --git 
a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py 
b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
index 8366e4dd8..72cf633d5 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
@@ -140,7 +140,7 @@ def test_delete_undelete(self):
         r = form.submit()
         r = self.app.get('/admin/discussion/forums')
         soup_form = r.html.find('form', action='update_forums')
-        assert len(soup_form.findAll('input', {'value': 'Delete'})) == 2
+        assert len(soup_form.find_all('input', {'value': 'Delete'})) == 2
         h.set_context('test', 'Forum', neighborhood='Projects')
         frm = FM.Forum.query.get(shortname='testforum')
 
@@ -151,7 +151,7 @@ def test_delete_undelete(self):
                                   'forum-0.description': 'My desc'})
         r = self.app.get('/admin/discussion/forums')
         soup_form = r.html.find('form', action='update_forums')
-        assert len(soup_form.findAll('input', {'value': 'Delete'})) == 1
+        assert len(soup_form.find_all('input', {'value': 'Delete'})) == 1
         audit_log = M.AuditLog.query.find({'project_id': 
project._id}).sort('_id', -1).first()
         assert 'deleted forum "Test Forum"' in audit_log.message
         r = self.app.post('/admin/discussion/update_forums',
@@ -161,7 +161,7 @@ def test_delete_undelete(self):
                                   'forum-0.description': 'My desc'})
         r = self.app.get('/admin/discussion/forums')
         soup_form = r.html.find('form', action='update_forums')
-        assert len(soup_form.findAll('input', {'value': 'Delete'})) == 2
+        assert len(soup_form.find_all('input', {'value': 'Delete'})) == 2
         audit_log = M.AuditLog.query.find({'project_id': 
project._id}).sort('_id', -1).first()
         assert 'undeleted forum "Test Forum"' in audit_log.message
 
@@ -182,7 +182,7 @@ def test_members_only(self):
         f = r.html.find(
             'form', {'action': '/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -236,7 +236,7 @@ def test_anon_posts(self):
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': 
'/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -261,7 +261,7 @@ def test_anon_posts(self):
         f = r.html.find(
             'form', {'action': '/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -304,7 +304,7 @@ def test_footer_monitoring_email(self):
         f = r.html.find(
             'form', {'action': '/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py 
b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
index 633775360..84c64ccef 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
@@ -56,7 +56,7 @@ def test_import_anon(self):
             r = self.app.get('/p/test/discussion/')
             assert 'Open Discussion' in str(r)
             assert 'Welcome to Open Discussion' in str(r)
-            for link in r.html.findAll('a'):
+            for link in r.html.find_all('a'):
                 if 'Welcome to Open Discussion' in str(link):
                     break
             r = self.app.get(link.get('href'))
@@ -73,7 +73,7 @@ def test_import_map(self):
             r = self.app.get('/p/test/discussion/')
             assert 'Open Discussion' in str(r)
             assert 'Welcome to Open Discussion' in str(r)
-            for link in r.html.findAll('a'):
+            for link in r.html.find_all('a'):
                 if 'Welcome to Open Discussion' in str(link):
                     break
             r = self.app.get(link.get('href'))
@@ -90,7 +90,7 @@ def test_import_create(self):
             r = self.app.get('/p/test/discussion/')
             assert 'Open Discussion' in str(r)
             assert 'Welcome to Open Discussion' in str(r)
-            for link in r.html.findAll('a'):
+            for link in r.html.find_all('a'):
                 if 'Welcome to Open Discussion' in str(link):
                     break
             r = self.app.get(link.get('href'))
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py 
b/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
index 379078fef..110f80fe4 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
@@ -49,7 +49,7 @@ def create_topic(self, forum, subject, text):
         f = r.html.find(
             'form', {'action': '/p/test/discussion/save_new_topic'})
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
diff --git a/ForgeGit/forgegit/tests/functional/test_controllers.py 
b/ForgeGit/forgegit/tests/functional/test_controllers.py
index f9edeaf6d..466dd8692 100644
--- a/ForgeGit/forgegit/tests/functional/test_controllers.py
+++ b/ForgeGit/forgegit/tests/functional/test_controllers.py
@@ -99,7 +99,7 @@ def test_repo_loading(self):
 
     def test_status_html(self):
         resp = 
self.app.get('/src-git/ci/e0d7765883017040d53f9ca9c528940a4dd311c6/')
-        sortedCommits = resp.html.findAll('td')
+        sortedCommits = resp.html.find_all('td')
         actualCommit = ['added', 'aaa.txt',
                         'removed', 'bbb.txt',
                         'changed', 'ccc.txt',
@@ -107,7 +107,7 @@ def test_status_html(self):
                         'added', 'eee.txt',
                         'added', 'ggg.txt']
         for i, item in enumerate(sortedCommits):
-            assert actualCommit[i] == 
''.join(item.findAll(string=True)).strip()
+            assert actualCommit[i] == 
''.join(item.find_all(string=True)).strip()
 
 
 class TestRootController(_TestCase):
@@ -172,10 +172,10 @@ def test_log(self):
         assert 'Initial commit' in resp
         assert '<div class="markdown_content"><p>Change README</div>' in resp, 
resp
         assert 'tree/README?format=raw">Download</a>' not in resp
-        assert 'Tree' in resp.html.findAll('td')[2].text, 
resp.html.findAll('td')[2].text
-        assert 'by Rick Copeland' in 
squish_spaces(resp.html.findAll('td')[0].text)
+        assert 'Tree' in resp.html.find_all('td')[2].text, 
resp.html.find_all('td')[2].text
+        assert 'by Rick Copeland' in 
squish_spaces(resp.html.find_all('td')[0].text)
         resp = 
self.app.get('/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/?path=/README')
-        assert 'View' in resp.html.findAll('td')[2].text
+        assert 'View' in resp.html.find_all('td')[2].text
         assert 'Change README' in resp
         assert 'tree/README?format=raw">Download</a>' in resp
         assert 'Add README' in resp
@@ -210,7 +210,7 @@ def test_tags(self):
     def _get_ci(self, repo='/p/test/src-git/'):
         r = self.app.get(repo + 'ref/master/')
         resp = r.follow()
-        for tag in resp.html.findAll('a'):
+        for tag in resp.html.find_all('a'):
             if tag['href'].startswith(repo + 'ci/'):
                 href = tag['href']
                 if href.endswith('tree/'):
@@ -255,10 +255,10 @@ def test_feed(self):
     def test_tree(self):
         ci = self._get_ci()
         resp = self.app.get(ci + 'tree/')
-        assert len(resp.html.findAll('tr')) == 2, resp.showbrowser()
+        assert len(resp.html.find_all('tr')) == 2, resp.showbrowser()
         resp = self.app.get(ci + 'tree/')
         assert 'README' in resp, resp.showbrowser()
-        links = [a.get('href') for a in resp.html.findAll('a')]
+        links = [a.get('href') for a in resp.html.find_all('a')]
         assert 'README' in links, resp.showbrowser()
         assert 'README/' not in links, resp.showbrowser()
 
@@ -727,7 +727,7 @@ def test_merge_request_detail_view(self):
         r, mr_num = self._request_merge()
         assert 'wants to merge' in r
 
-        merge_instructions = r.html.findAll('textarea')[0].getText()
+        merge_instructions = r.html.find_all('textarea')[0].getText()
         assert 'git checkout master' in merge_instructions
         assert 'git fetch /srv/git/p/test2/code master' in merge_instructions
         c_id = self.forked_repo.get_heads()[0]['object_id']
@@ -749,10 +749,10 @@ def test_merge_request_detail_view(self):
 
         def assert_commit_details(r):
             assert 'Improve documentation' in r.text
-            revs = r.html.findAll('tr', attrs={'class': 'rev'})
+            revs = r.html.find_all('tr', attrs={'class': 'rev'})
             assert len(revs) == 1
-            rev_links = revs[0].findAll('a', attrs={'class': 'rev'})
-            browse_links = revs[0].findAll('a', attrs={'class': 'browse'})
+            rev_links = revs[0].find_all('a', attrs={'class': 'rev'})
+            browse_links = revs[0].find_all('a', attrs={'class': 'browse'})
             assert rev_links[0].get('href') == '/p/test2/code/ci/%s/' % c_id
             assert rev_links[0].getText() == '[%s]' % c_id[:6]
             assert (browse_links[0].get('href') ==
@@ -795,8 +795,8 @@ def test_merge_request_list_view(self):
         r, mr_num = self._request_merge()
         r = self.app.get('/p/test/src-git/merge-requests/')
         assert 'href="%s/"' % mr_num in r, r
-        assert_regexp_matches(r.html.findAll('span')[-2].getText(), r'[0-9]+ 
seconds? ago')
-        assert_regexp_matches(r.html.findAll('span')[-1].getText(), r'[0-9]+ 
seconds? ago')
+        assert_regexp_matches(r.html.find_all('span')[-2].getText(), r'[0-9]+ 
seconds? ago')
+        assert_regexp_matches(r.html.find_all('span')[-1].getText(), r'[0-9]+ 
seconds? ago')
 
         r = self.app.get('/p/test/src-git/merge-requests/?status=rejected')
         assert 'href="%s/"' % mr_num not in r, r
@@ -893,7 +893,7 @@ def test_merge_request_edit(self):
         assert '[5c4724]' not in r
         assert '<p>changed description</p' in r
         assert 'Merge Request #1: changed summary (open)' in r
-        changes = r.html.findAll('div', attrs={'class': 
'markdown_content'})[-1]
+        changes = r.html.find_all('div', attrs={'class': 
'markdown_content'})[-1]
         assert str(changes) == """
 <div class="markdown_content"><ul>
 <li>
diff --git a/ForgeImporters/forgeimporters/github/wiki.py 
b/ForgeImporters/forgeimporters/github/wiki.py
index a36e0e858..56dfb2270 100644
--- a/ForgeImporters/forgeimporters/github/wiki.py
+++ b/ForgeImporters/forgeimporters/github/wiki.py
@@ -415,7 +415,7 @@ def rewrite_links(self, html, prefix, new_prefix):
         if not new_prefix.endswith('/'):
             new_prefix += '/'
         soup = BeautifulSoup(html, 'html.parser')
-        for a in soup.findAll('a'):
+        for a in soup.find_all('a'):
             if a.get('href').startswith(prefix):
                 page = a['href'].replace(prefix, '')
                 new_page = self._convert_page_name(page)
diff --git a/ForgeSVN/forgesvn/tests/functional/test_controllers.py 
b/ForgeSVN/forgesvn/tests/functional/test_controllers.py
index d294b0bc1..4953d8a94 100644
--- a/ForgeSVN/forgesvn/tests/functional/test_controllers.py
+++ b/ForgeSVN/forgesvn/tests/functional/test_controllers.py
@@ -137,7 +137,7 @@ def test_feed(self):
 
     def test_commit(self):
         resp = self.app.get('/src/3/tree/')
-        assert len(resp.html.findAll('tr')) == 3, resp.showbrowser()
+        assert len(resp.html.find_all('tr')) == 3, resp.showbrowser()
 
     def test_commit_unicode_and_special_chars(self):
         resp = self.app.get('/src/6/')
@@ -171,9 +171,9 @@ def test_commit_unicode_and_special_chars(self):
 
     def test_tree(self):
         resp = self.app.get('/src/1/tree/')
-        assert len(resp.html.findAll('tr')) == 2, resp.showbrowser()
+        assert len(resp.html.find_all('tr')) == 2, resp.showbrowser()
         resp = self.app.get('/src/3/tree/a/')
-        assert len(resp.html.findAll('tr')) == 2, resp.showbrowser()
+        assert len(resp.html.find_all('tr')) == 2, resp.showbrowser()
 
     def test_file(self):
         resp = self.app.get('/src/1/tree/README')
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py 
b/ForgeTracker/forgetracker/tests/functional/test_root.py
index a392db564..6661b7ac2 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -572,7 +572,7 @@ def test_mass_edit_select_options_split(self):
             params=variable_encode(params))
         r = self.app.get('/p/test/bugs/edit/')
         opts = r.html.find('select', attrs={'name': '_type'})
-        opts = opts.findAll('option')
+        opts = opts.find_all('option')
         assert opts[0].get('value') == ''
         assert opts[0].getText() == 'no change'
         assert opts[1].get('value') == 'Bug'
@@ -876,8 +876,8 @@ def test_new_attachment(self):
         assert file_name in ticket_editor
         assert '<span>py</span>' not in ticket_editor
         ticket_page = self.app.get('/bugs/1/')
-        diff = ticket_page.html.findAll('div', attrs={'class': 'codehilite'})
-        added = diff[-1].findAll('span', attrs={'class': 'gi'})[-1]
+        diff = ticket_page.html.find_all('div', attrs={'class': 'codehilite'})
+        added = diff[-1].find_all('span', attrs={'class': 'gi'})[-1]
         assert '+test_root.py' in added.getText()
 
     def test_delete_attachment(self):
@@ -891,24 +891,24 @@ def test_delete_attachment(self):
         assert file_name in ticket_editor, ticket_editor.showbrowser()
         req = self.app.get('/bugs/1/')
         form = self._find_update_ticket_form(req)
-        file_link = BeautifulSoup(form.text, 
features="html5lib").findAll('a')[2]
+        file_link = BeautifulSoup(form.text, 
features="html5lib").find_all('a')[2]
         assert file_link.string == file_name
         self.app.post(str(file_link['href']), {
             'delete': 'True'
         })
         ticket_page = self.app.get('/bugs/1/')
         assert '/p/test/bugs/1/attachment/test_root.py' not in ticket_page
-        diff = ticket_page.html.findAll('div', attrs={'class': 'codehilite'})
-        removed = diff[-1].findAll('span', attrs={'class': 'gd'})[-1]
+        diff = ticket_page.html.find_all('div', attrs={'class': 'codehilite'})
+        removed = diff[-1].find_all('span', attrs={'class': 'gd'})[-1]
         assert '-test_root.py' in removed.getText()
 
     def test_delete_attachment_from_comments(self):
         ticket_view = self.new_ticket(summary='test ticket').follow()
-        for f in ticket_view.html.findAll('form'):
+        for f in ticket_view.html.find_all('form'):
             if f.get('action', '').endswith('/post'):
                 break
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -934,7 +934,7 @@ def test_new_text_attachment_content(self):
             'summary': 'zzz'
         }, upload_files=[upload]).follow()
         form = self._find_update_ticket_form(ticket_editor)
-        download = self.app.get(str(BeautifulSoup(form.text, 
features="html5lib").findAll('a')[2]['href']))
+        download = self.app.get(str(BeautifulSoup(form.text, 
features="html5lib").find_all('a')[2]['href']))
         assert download.body == file_data
 
     def test_two_attachments(self):
@@ -1322,7 +1322,7 @@ def test_new_ticket_validation(self):
         # set a summary, submit, and check for success
         form['ticket_form.summary'] = summary
         success = form.submit().follow().html
-        assert success.findAll('form', {'action': 
'/p/test/bugs/1/update_ticket_from_widget'}) is not None
+        assert success.find_all('form', {'action': 
'/p/test/bugs/1/update_ticket_from_widget'}) is not None
         assert success.find('input', {'name': 'ticket_form.summary'})['value'] 
== summary
 
     def test_edit_ticket_validation(self):
@@ -1347,7 +1347,7 @@ def test_edit_ticket_validation(self):
         r = form.submit()
         assert r.status_int == 302, r.showbrowser()
         success = r.follow().html
-        assert success.findAll('form', {'action': 
'/p/test/bugs/1/update_ticket_from_widget'}) is not None
+        assert success.find_all('form', {'action': 
'/p/test/bugs/1/update_ticket_from_widget'}) is not None
         assert success.find('input', {'name': 'ticket_form.summary'})['value'] 
== new_summary
 
     def test_home(self):
@@ -1524,12 +1524,12 @@ def test_edit_saved_search(self):
     def test_comment_split(self):
         summary = 'new ticket'
         ticket_view = self.new_ticket(summary=summary).follow()
-        for f in ticket_view.html.findAll('form'):
+        for f in ticket_view.html.find_all('form'):
             if f.get('action', '').endswith('/post'):
                 break
         post_content = 'ticket discussion post content'
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -1538,14 +1538,14 @@ def test_comment_split(self):
                           headers={'Referer': b'/bugs/1/'})
         r = self.app.get('/bugs/1/', dict(page='1'))
         assert post_content in r
-        assert len(r.html.findAll(attrs={'class': 'discussion-post'})) == 1
+        assert len(r.html.find_all(attrs={'class': 'discussion-post'})) == 1
 
         new_summary = 'old ticket'
-        for f in ticket_view.html.findAll('form'):
+        for f in ticket_view.html.find_all('form'):
             if f.get('action', '').endswith('update_ticket_from_widget'):
                 break
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -1554,17 +1554,17 @@ def test_comment_split(self):
                           headers={'Referer': b'/bugs/1/'})
         r = self.app.get('/bugs/1/', dict(page='1'))
         assert summary + ' --&gt; ' + new_summary in r
-        assert len(r.html.findAll(attrs={'class': 'discussion-post 
meta_post'})) == 1
+        assert len(r.html.find_all(attrs={'class': 'discussion-post 
meta_post'})) == 1
 
     def test_discussion_paging(self):
         summary = 'test discussion paging'
         ticket_view = self.new_ticket(summary=summary).follow()
-        for f in ticket_view.html.findAll('form'):
+        for f in ticket_view.html.find_all('form'):
             if f.get('action', '').endswith('/post'):
                 break
         post_content = 'ticket discussion post content'
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -1587,12 +1587,12 @@ def test_discussion_paging(self):
     def test_discussion_feed(self):
         summary = 'test discussion paging'
         ticket_view = self.new_ticket(summary=summary).follow()
-        for f in ticket_view.html.findAll('form'):
+        for f in ticket_view.html.find_all('form'):
             if f.get('action', '').endswith('/post'):
                 break
         post_content = 'ticket discussion post content'
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -1606,7 +1606,7 @@ def test_discussion_feed(self):
         post_link = str(r.html.find('div', {'class': 'edit_post_form 
reply'}).find('form')['action'])
         post_form = r.html.find('form', {'action': post_link + 'reply'})
         params = dict()
-        inputs = post_form.findAll('input')
+        inputs = post_form.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -2164,7 +2164,7 @@ def test_show_hide_deleted_tickets(self):
     def test_move_ticket(self):
         self.new_ticket(summary='test')
         r = self.app.get('/p/test/bugs/1/move')
-        trackers = r.html.find('select', {'name': 'tracker'}).findAll('option')
+        trackers = r.html.find('select', {'name': 
'tracker'}).find_all('option')
         trackers = {t.text for t in trackers}
         expected = {'test/bugs', 'test/bugs2', 'test2/bugs', 'test2/bugs2'}
         assert trackers == expected, trackers
@@ -2174,7 +2174,7 @@ def test_move_ticket(self):
         r = self.app.post('/p/test/bugs/1/move/',
                           params={'tracker': str(tracker.config._id)}).follow()
         assert r.request.path == '/p/test2/bugs2/1/'
-        summary = r.html.findAll('h2', {'class': 'dark 
title'})[0].find('span').contents[0].strip()
+        summary = r.html.find_all('h2', {'class': 'dark 
title'})[0].find('span').contents[0].strip()
         assert summary == '#1 test'
         ac_id = tracker.config._id
         ticket = tm.Ticket.query.find({
@@ -2212,12 +2212,12 @@ def test_move_ticket_feed(self):
 
         # post comment and make sure that it appears on the feeds
         r = self.app.get('/p/test2/bugs2/1/')
-        for f in r.html.findAll('form'):
+        for f in r.html.find_all('form'):
             if f.get('action', '').endswith('/post'):
                 break
         post_content = 'ticket discussion post content'
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -2226,7 +2226,7 @@ def test_move_ticket_feed(self):
                           headers={'Referer': b'/p/test2/bugs2/1/'})
         r = self.app.get('/p/test2/bugs2/1/', dict(page='1'))
         assert post_content in r
-        comments_cnt = len(r.html.findAll(attrs={'class': 'discussion-post'}))
+        comments_cnt = len(r.html.find_all(attrs={'class': 'discussion-post'}))
         assert comments_cnt == 2  # moved auto comment + new comment
         post = ticket.discussion_thread.last_post
         # content and link to the ticket should be in a tracker's feed
@@ -2410,8 +2410,8 @@ def test_move_attachment(self):
         r = self.app.post('/p/test/bugs/1/move/',
                           params={'tracker': str(bugs2.config._id)}).follow()
 
-        attach_tickets = r.html.findAll('div', attrs={'class': 
'attachment_thumb'})
-        attach_comments = r.html.findAll('div', attrs={'class': 
'attachment_item'})
+        attach_tickets = r.html.find_all('div', attrs={'class': 
'attachment_thumb'})
+        attach_comments = r.html.find_all('div', attrs={'class': 
'attachment_item'})
         ta = str(attach_tickets)  # ticket's attachments
         ca = str(attach_comments)  # comment's attachments
         assert '<a 
href="/p/test2/bugs2/1/attachment/neo-icon-set-454545-256x350.png"' in ta
@@ -2463,11 +2463,11 @@ def test_tags(self):
 
     def test_rest_tickets(self):
         ticket_view = self.new_ticket(summary='test').follow()
-        for f in ticket_view.html.findAll('form'):
+        for f in ticket_view.html.find_all('form'):
             if f.get('action', '').endswith('/post'):
                 break
         params = dict()
-        inputs = f.findAll('input')
+        inputs = f.find_all('input')
         for field in inputs:
             if field.has_attr('name'):
                 params[field['name']] = field.get('value') or ''
@@ -2479,7 +2479,7 @@ def test_rest_tickets(self):
         self.app.post(post_link + 'attach',
                       upload_files=[('file_info', 'test.txt', b'test attach')])
         r = self.app.get('/p/test/bugs/1/')
-        discussion_url = r.html.findAll('form')[-1]['action'][:-4]
+        discussion_url = r.html.find_all('form')[-1]['action'][:-4]
         r = self.app.get('/rest/p/test/bugs/1/')
         r = json.loads(r.text)
         assert (r['ticket']['discussion_thread_url'] ==
@@ -2757,8 +2757,8 @@ def _set_options(self, 
monitoring_type='AllTicketChanges'):
     def test_set_options(self):
         r = self._set_options()
         r = self.app.get('/admin/bugs/options')
-        email = r.html.findAll(attrs=dict(name='TicketMonitoringEmail'))
-        mtype = r.html.findAll('option', attrs=dict(value='AllTicketChanges'))
+        email = r.html.find_all(attrs=dict(name='TicketMonitoringEmail'))
+        mtype = r.html.find_all('option', attrs=dict(value='AllTicketChanges'))
         assert email[0]['value'] == self.test_email
         assert mtype[0].has_attr('selected')
 
@@ -2817,11 +2817,11 @@ def test_notifications_all(self, send_simple):
         send_simple.assert_called_with(self.test_email)
         send_simple.reset_mock()
         response = response.follow()
-        for f in response.html.findAll('form'):
+        for f in response.html.find_all('form'):
             # Dirty way to find comment form
             if (('thread' in f['action']) and ('post' in f['action'])):
                 params = {i['name']: i.get('value', '')
-                          for i in f.findAll('input')
+                          for i in f.find_all('input')
                           if i.has_attr('name')}
                 params[f.find('textarea')['name']] = 'foobar'
                 self.app.post(str(f['action']), params)
@@ -2894,7 +2894,7 @@ def test_blank_user(self):
         kw = {'custom_fields._code_review': ''}
         ticket_view = self.new_ticket(summary='test custom fields', 
**kw).follow()
         # summary header shows 'nobody'
-        assert (squish_spaces(ticket_view.html.findAll('label', 'simple', 
text='Code Review:')[0].parent.text) ==
+        assert (squish_spaces(ticket_view.html.find_all('label', 'simple', 
text='Code Review:')[0].parent.text) ==
                 ' Code Review: nobody ')
         # form input is blank
         select = ticket_view.html.find('select',
@@ -2909,7 +2909,7 @@ def test_project_member(self):
         kw = {'custom_fields._code_review': 'test-admin'}
         ticket_view = self.new_ticket(summary='test custom fields', 
**kw).follow()
         # summary header shows 'Test Admin'
-        assert (squish_spaces(ticket_view.html.findAll('label', 'simple', 
text='Code Review:')[0].parent.text) ==
+        assert (squish_spaces(ticket_view.html.find_all('label', 'simple', 
text='Code Review:')[0].parent.text) ==
                 ' Code Review: Test Admin ')
         # form input is blank
         select = ticket_view.html.find('select',
@@ -2932,8 +2932,8 @@ def test_search_results(self):
         kw = {'custom_fields._code_review': 'test-admin'}
         self.new_ticket(summary='test custom fields', **kw)
         r = self.app.get('/bugs/')
-        assert r.html.find('table', 
'ticket-list').findAll('th')[7].text.strip()[:11] == 'Code Review'
-        assert r.html.find('table', 
'ticket-list').tbody.tr.findAll('td')[7].text == 'Test Admin'
+        assert r.html.find('table', 
'ticket-list').find_all('th')[7].text.strip()[:11] == 'Code Review'
+        assert r.html.find('table', 
'ticket-list').tbody.tr.find_all('td')[7].text == 'Test Admin'
 
 
 class TestHelpTextOptions(TrackerTestController):
@@ -2960,15 +2960,15 @@ def test_help_text(self):
         self._set_options()
         r = self.app.get('/bugs/')
         assert len(
-            r.html.findAll(attrs=dict(id='search-ticket-help-msg'))) == 0
+            r.html.find_all(attrs=dict(id='search-ticket-help-msg'))) == 0
         r = self.app.get('/bugs/search/', params=dict(q='test'))
         assert len(
-            r.html.findAll(attrs=dict(id='search-ticket-help-msg'))) == 0
+            r.html.find_all(attrs=dict(id='search-ticket-help-msg'))) == 0
         r = self.app.get('/bugs/milestone/1.0/')
         assert len(
-            r.html.findAll(attrs=dict(id='search-ticket-help-msg'))) == 0
+            r.html.find_all(attrs=dict(id='search-ticket-help-msg'))) == 0
         r = self.app.get('/bugs/new/')
-        assert len(r.html.findAll(attrs=dict(id='new-ticket-help-msg'))) == 0
+        assert len(r.html.find_all(attrs=dict(id='new-ticket-help-msg'))) == 0
 
 
 class TestShowDefaultFields(TrackerTestController):
@@ -3030,7 +3030,7 @@ def test_access_restriction(self):
     def test_ticket_list(self):
         r = self.app.get('/bugs/move/?q=The')
         tickets_table = r.html.find('tbody', attrs={'class': 'ticket-list'})
-        tickets = tickets_table.findAll('tr')
+        tickets = tickets_table.find_all('tr')
         assert len(tickets) == 2
         assert 'The Empire Strikes Back' in tickets_table.text
         assert 'Return Of The Jedi' in tickets_table.text
@@ -3040,7 +3040,7 @@ def test_ticket_list(self):
     @td.with_tool('test2', 'Tickets', 'bugs2')
     def test_controls_present(self):
         r = self.app.get('/bugs/move/')
-        trackers = r.html.find('select', {'name': 'tracker'}).findAll('option')
+        trackers = r.html.find('select', {'name': 
'tracker'}).find_all('option')
         trackers = {t.text for t in trackers}
         expected = {'test/bugs', 'test/bugs2', 'test2/bugs', 'test2/bugs2'}
         assert trackers == expected
diff --git a/ForgeWiki/forgewiki/converters.py 
b/ForgeWiki/forgewiki/converters.py
index 5a194e4f8..318ce6156 100644
--- a/ForgeWiki/forgewiki/converters.py
+++ b/ForgeWiki/forgewiki/converters.py
@@ -50,7 +50,7 @@ def _internal_link_markdown(match):
 def _convert_toc(wiki_html):
     """Convert Table of Contents from mediawiki to markdown"""
     soup = BeautifulSoup(wiki_html, 'html.parser')
-    for toc_div in soup.findAll('div', id='toc'):
+    for toc_div in soup.find_all('div', id='toc'):
         toc_div.replaceWith('[TOC]')
     return str(soup)
 
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py 
b/ForgeWiki/forgewiki/tests/functional/test_root.py
index 2d8aaef19..7b5b30a4f 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -583,7 +583,7 @@ def test_new_image_attachment_content(self):
 
         # Make sure thumbnail is absent
         r = self.app.get('/wiki/TEST/')
-        img_srcs = [i['src'] for i in r.html.findAll('img')]
+        img_srcs = [i['src'] for i in r.html.find_all('img')]
         assert ('/p/test/wiki/TEST/attachment/' +
                 filename) not in img_srcs, img_srcs
 
@@ -743,7 +743,7 @@ def test_page_links_are_colored(self):
                       upload_files=[('file_info', 'test_root.py', content)])
         r = self.app.get('/wiki/TEST/')
         found_links = 0
-        for link in r.html.findAll('a'):
+        for link in r.html.find_all('a'):
             if link.contents == ['this page']:
                 assert 'notfound' not in link.get('class', [])
                 found_links += 1
@@ -847,7 +847,7 @@ def test_mailto_links(self):
         self.app.post('/wiki/test_mailto/update', params=params)
         r = self.app.get('/wiki/test_mailto/')
         mailto_links = 0
-        for link in r.html.findAll('a'):
+        for link in r.html.find_all('a'):
             if link.get('href') == 'mailto:[email protected]':
                 assert 'notfound' not in link.get('class', '')
                 mailto_links += 1
@@ -961,7 +961,7 @@ def test_sidebar_admin_menu(self):
         r = self.app.get('/p/test/wiki/Home/')
         menu = r.html.find('div', {'id': 'sidebar-admin-menu'})
         assert menu['class'] == ['hidden']  # (not expanded)
-        menu = [li.find('span').getText() for li in menu.findAll('li')]
+        menu = [li.find('span').getText() for li in menu.find_all('li')]
         assert (
             menu ==
             ['Set Home', 'Permissions', 'Options', 'Rename', 'Delete 
Everything'])


Reply via email to