diff --git a/reviewboard/extensions/hooks.py b/reviewboard/extensions/hooks.py
index c18cb68cc12a14a1dbaf4a805320aad6872b9c79..24e87b31405f6a78a8a0c1a3d3859b727ee9d820 100644
--- a/reviewboard/extensions/hooks.py
+++ b/reviewboard/extensions/hooks.py
@@ -3,7 +3,6 @@ from __future__ import unicode_literals
 import logging
 import warnings
 
-from django.utils import six
 from django.utils.translation import ugettext as _
 from djblets.extensions.hooks import (AppliesToURLMixin,
                                       BaseRegistryHook,
@@ -52,8 +51,7 @@ from reviewboard.webapi.server_info import (register_webapi_capabilities,
 logger = logging.getLogger(__name__)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class AuthBackendHook(BaseRegistryHook):
+class AuthBackendHook(BaseRegistryHook, metaclass=ExtensionHookPoint):
     """A hook for registering an authentication backend.
 
     Authentication backends control user authentication, registration, user
@@ -79,8 +77,7 @@ class AuthBackendHook(BaseRegistryHook):
         super(AuthBackendHook, self).initialize(backend_cls)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class AvatarServiceHook(BaseRegistryHook):
+class AvatarServiceHook(BaseRegistryHook, metaclass=ExtensionHookPoint):
     """"A hook for adding avatar services.
 
     This hook will register services with the avatar services registry and
@@ -102,8 +99,8 @@ class AvatarServiceHook(BaseRegistryHook):
         super(AvatarServiceHook, self).initialize(service)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class AccountPagesHook(BaseRegistryMultiItemHook):
+class AccountPagesHook(BaseRegistryMultiItemHook,
+                       metaclass=ExtensionHookPoint):
     """A hook for adding new pages to the My Account page.
 
     A page can contain one or more forms or even a custom template allowing
@@ -129,8 +126,7 @@ class AccountPagesHook(BaseRegistryMultiItemHook):
         super(AccountPagesHook, self).initialize(page_classes)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class AccountPageFormsHook(ExtensionHook):
+class AccountPageFormsHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """A hook for adding new forms to a page in the My Account page.
 
     This is used to add custom forms to a page in the My Account page. The
@@ -188,8 +184,7 @@ class AccountPageFormsHook(ExtensionHook):
             page_class.remove_form(form_class)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class AdminWidgetHook(BaseRegistryHook):
+class AdminWidgetHook(BaseRegistryHook, metaclass=ExtensionHookPoint):
     """A hook for adding a new widget to the administration dashboard.
 
     Version Changed::
@@ -237,8 +232,7 @@ class AdminWidgetHook(BaseRegistryHook):
         super(AdminWidgetHook, self).initialize(widget_cls)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class DataGridSidebarItemsHook(ExtensionHook):
+class DataGridSidebarItemsHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """A hook for adding items to the sidebar of a datagrid.
 
     Extensions can use this hook to plug new items into the sidebar of
@@ -318,8 +312,8 @@ class DashboardColumnsHook(DataGridColumnsHook):
                                                      columns)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class DashboardSidebarItemsHook(DataGridSidebarItemsHook):
+class DashboardSidebarItemsHook(DataGridSidebarItemsHook,
+                                metaclass=ExtensionHookPoint):
     """A hook for adding items to the sidebar of the dashboard.
 
     Extensions can use this hook to plug new items into the sidebar of
@@ -347,8 +341,7 @@ class DashboardSidebarItemsHook(DataGridSidebarItemsHook):
                                                           item_classes)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class HostingServiceHook(ExtensionHook):
+class HostingServiceHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """A hook for registering a hosting service."""
 
     def initialize(self, service_cls):
@@ -384,8 +377,8 @@ class HostingServiceHook(ExtensionHook):
         unregister_hosting_service(self.hosting_service_id)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class IntegrationHook(GetIntegrationManagerMixin, BaseIntegrationHook):
+class IntegrationHook(GetIntegrationManagerMixin, BaseIntegrationHook,
+                      metaclass=ExtensionHookPoint):
     """A hook for registering new integration classes.
 
     Integrations enable Review Board to connect with third-party services in
@@ -394,8 +387,7 @@ class IntegrationHook(GetIntegrationManagerMixin, BaseIntegrationHook):
     """
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class NavigationBarHook(ExtensionHook):
+class NavigationBarHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """A hook for adding entries to the main navigation bar.
 
     This takes a list of entries. Each entry represents something
@@ -481,8 +473,7 @@ class NavigationBarHook(ExtensionHook):
             return []
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class ReviewRequestApprovalHook(ExtensionHook):
+class ReviewRequestApprovalHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """A hook for determining if a review request is approved.
 
     Extensions can use this to hook into the process for determining
@@ -529,8 +520,7 @@ class ReviewRequestApprovalHook(ExtensionHook):
         raise NotImplementedError
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class ReviewRequestFieldSetsHook(ExtensionHook):
+class ReviewRequestFieldSetsHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """A hook for creating fieldsets on the side of the review request page.
 
     A fieldset contains one or more fields, and is mainly used to separate
@@ -572,8 +562,7 @@ class ReviewRequestFieldSetsHook(ExtensionHook):
             unregister_review_request_fieldset(fieldset)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class ReviewRequestFieldsHook(ExtensionHook):
+class ReviewRequestFieldsHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """A hook for creating fields on the review request page.
 
     This is used to create custom fields on a review request page for
@@ -637,8 +626,7 @@ class ReviewRequestFieldsHook(ExtensionHook):
             fieldset.remove_field(field_cls)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class WebAPICapabilitiesHook(ExtensionHook):
+class WebAPICapabilitiesHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """This hook allows adding capabilities to the web API server info.
 
     Note that this does not add the functionality, but adds to the server
@@ -673,8 +661,7 @@ class WebAPICapabilitiesHook(ExtensionHook):
         unregister_webapi_capabilities(self.extension.id)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class CommentDetailDisplayHook(ExtensionHook):
+class CommentDetailDisplayHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """This hook allows adding details to the display of comments.
 
     The hook can provide additional details to display for a comment in a
@@ -723,8 +710,7 @@ class CommentDetailDisplayHook(ExtensionHook):
         raise NotImplementedError
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class ReviewUIHook(ExtensionHook):
+class ReviewUIHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """This hook allows integration of Extension-defined Review UIs.
 
     This accepts a list of Review UIs specified by the Extension and
@@ -762,8 +748,7 @@ class ReviewUIHook(ExtensionHook):
             unregister_ui(review_ui)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class FileAttachmentThumbnailHook(ExtensionHook):
+class FileAttachmentThumbnailHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """This hook allows custom thumbnails to be defined for file attachments.
 
     This accepts a list of mimetype handlers specified by the Extension
@@ -965,8 +950,8 @@ class _DictMenuAction(BaseReviewRequestMenuAction):
         return self._applies_to(context['request'])
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class BaseReviewRequestActionHook(AppliesToURLMixin, ActionHook):
+class BaseReviewRequestActionHook(AppliesToURLMixin, ActionHook,
+                                  metaclass=ExtensionHookPoint):
     """A base hook for adding review request actions to the action bar.
 
     Review request actions are displayed on the action bar (alongside default
@@ -1140,8 +1125,8 @@ class BaseReviewRequestActionHook(AppliesToURLMixin, ActionHook):
         return _DictAction(action_dict, self.applies_to)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class ReviewRequestActionHook(BaseReviewRequestActionHook):
+class ReviewRequestActionHook(BaseReviewRequestActionHook,
+                              metaclass=ExtensionHookPoint):
     """A hook for adding review request actions to review request pages.
 
     By default, actions that are passed into this hook will only be displayed
@@ -1177,8 +1162,8 @@ class ReviewRequestActionHook(BaseReviewRequestActionHook):
             apply_to=apply_to or [main_review_request_url_name])
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class ReviewRequestDropdownActionHook(ReviewRequestActionHook):
+class ReviewRequestDropdownActionHook(ReviewRequestActionHook,
+                                      metaclass=ExtensionHookPoint):
     """A hook for adding dropdown menu actions to review request pages.
 
     Each menu action should be an instance of
@@ -1252,8 +1237,8 @@ class ReviewRequestDropdownActionHook(ReviewRequestActionHook):
         )
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class DiffViewerActionHook(BaseReviewRequestActionHook):
+class DiffViewerActionHook(BaseReviewRequestActionHook,
+                           metaclass=ExtensionHookPoint):
     """A hook for adding review request actions to diff viewer pages.
 
     By default, actions that are passed into this hook will only be displayed
@@ -1287,18 +1272,15 @@ class DiffViewerActionHook(BaseReviewRequestActionHook):
             apply_to=apply_to or diffviewer_url_names)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class HeaderActionHook(ActionHook):
+class HeaderActionHook(ActionHook, metaclass=ExtensionHookPoint):
     """A hook for adding actions to the page header."""
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class HeaderDropdownActionHook(ActionHook):
+class HeaderDropdownActionHook(ActionHook, metaclass=ExtensionHookPoint):
     """A hook for adding dropdown menu actions to the page header."""
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class UserInfoboxHook(ExtensionHook):
+class UserInfoboxHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """A hook for adding information to the user infobox.
 
     Extensions can use this hook to add additional pieces of data to the box
@@ -1404,8 +1386,8 @@ class UserInfoboxHook(ExtensionHook):
             request=request)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class UserPageSidebarItemsHook(DataGridSidebarItemsHook):
+class UserPageSidebarItemsHook(DataGridSidebarItemsHook,
+                               metaclass=ExtensionHookPoint):
     """A hook for adding items to the sidebar of the user page.
 
     Extensions can use this hook to plug new items into the sidebar of
@@ -1433,8 +1415,7 @@ class UserPageSidebarItemsHook(DataGridSidebarItemsHook):
             UserPageReviewRequestDataGrid, item_classes)
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class EmailHook(ExtensionHook):
+class EmailHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """A hook for changing the recipients of e-mails.
 
     Extensions can use this hook to change the contents of the To and CC fields
@@ -1799,8 +1780,7 @@ class ReviewRequestPublishedEmailHook(EmailHook):
         return cc_field
 
 
-@six.add_metaclass(ExtensionHookPoint)
-class APIExtraDataAccessHook(ExtensionHook):
+class APIExtraDataAccessHook(ExtensionHook, metaclass=ExtensionHookPoint):
     """A hook for setting access states to extra data fields.
 
     Extensions can use this hook to register ``extra_data`` fields with
diff --git a/reviewboard/integrations/__init__.py b/reviewboard/integrations/__init__.py
index 9fa1b6cc6b509da7f08fcb76ac92ff200fc8b79b..d5cb44ab7611467d2caf2b4353f1df30cd5c4a93 100644
--- a/reviewboard/integrations/__init__.py
+++ b/reviewboard/integrations/__init__.py
@@ -11,8 +11,6 @@ use the versions in :py:mod:`reviewboard.integrations.base` instead.
 
 from __future__ import unicode_literals
 
-from django.utils import six
-
 from reviewboard.deprecation import RemovedInReviewBoard50Warning
 
 
@@ -89,8 +87,7 @@ class _ProxyIntegrationMetaClass(type):
         return type.__new__(cls, name, bases, d)
 
 
-@six.add_metaclass(_ProxyIntegrationMetaClass)
-class Integration(object):
+class Integration(object, metaclass=_ProxyIntegrationMetaClass):
     """Base class for an integration.
 
     Deprecated:
diff --git a/reviewboard/webapi/tests/test_api_token.py b/reviewboard/webapi/tests/test_api_token.py
index 5a8e94afd56bbec47e195066b3ad59a467f9b025..ed1f212068c31f0f5e63b92bbbeb62a52af7ba48 100644
--- a/reviewboard/webapi/tests/test_api_token.py
+++ b/reviewboard/webapi/tests/test_api_token.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.db.query import get_object_or_none
 from djblets.webapi.errors import PERMISSION_DENIED
 from kgb import SpyAgency
@@ -34,9 +33,8 @@ class APITokenTestsMixin(object):
     }
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(SpyAgency, ExtraDataListMixin, BaseWebAPITestCase,
-                        APITokenTestsMixin):
+                        APITokenTestsMixin, metaclass=BasicTestsMetaclass):
     """Testing the APITokenResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = 'users/<username>/api-tokens/'
@@ -144,9 +142,8 @@ class ResourceListTests(SpyAgency, ExtraDataListMixin, BaseWebAPITestCase,
         self.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase,
-                        APITokenTestsMixin):
+                        APITokenTestsMixin, metaclass=BasicTestsMetaclass):
     """Testing the APITokenResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = 'users/<username>/api-tokens/<id>/'
diff --git a/reviewboard/webapi/tests/test_archived_review_request.py b/reviewboard/webapi/tests/test_archived_review_request.py
index e00b8a31deb6497d5949a93e89b7c77d83cf756c..386f7bd08d0babf72fc39622804359ef808a8196 100644
--- a/reviewboard/webapi/tests/test_archived_review_request.py
+++ b/reviewboard/webapi/tests/test_archived_review_request.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.errors import DOES_NOT_EXIST
 
@@ -14,8 +13,7 @@ from reviewboard.webapi.tests.urls import (
     get_archived_review_request_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ArchivedReviewRequestResource list API tests"""
 
     fixtures = ['test_users']
@@ -81,8 +79,7 @@ class ResourceListTests(BaseWebAPITestCase):
         self.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ArchivedReviewRequestResource item API tests."""
 
     fixtures = ['test_users']
diff --git a/reviewboard/webapi/tests/test_default_reviewer.py b/reviewboard/webapi/tests/test_default_reviewer.py
index 6a4f0a8b3eba2303d3308cbaa7b2a8ac6e45581c..10cfe60e9d81d9a41e1e05ba54f61f06f6c451bc 100644
--- a/reviewboard/webapi/tests/test_default_reviewer.py
+++ b/reviewboard/webapi/tests/test_default_reviewer.py
@@ -17,8 +17,7 @@ from reviewboard.webapi.tests.urls import (get_default_reviewer_item_url,
                                            get_default_reviewer_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DefaultReviewerResource list APIs."""
     fixtures = ['test_users']
     basic_post_fixtures = ['test_scmtools']
@@ -446,8 +445,7 @@ class ResourceListTests(BaseWebAPITestCase):
         self.assertIn('repositories', rsp['fields'])
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DefaultReviewerResource item APIs."""
     fixtures = ['test_users']
     basic_get_fixtures = ['test_scmtools']
diff --git a/reviewboard/webapi/tests/test_diff.py b/reviewboard/webapi/tests/test_diff.py
index bd595a6cf101938ab5aa361d587538c855243d75..f07fc619bacf23b07d6fddbf5e65ff43eb68b6b0 100644
--- a/reviewboard/webapi/tests/test_diff.py
+++ b/reviewboard/webapi/tests/test_diff.py
@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 from django.core.files.uploadedfile import SimpleUploadedFile
-from django.utils import six
 from djblets.features.testing import override_feature_check
 from djblets.webapi.errors import (INVALID_ATTRIBUTE, INVALID_FORM_DATA,
                                    PERMISSION_DENIED)
@@ -24,9 +23,8 @@ from reviewboard.webapi.tests.urls import (get_diff_item_url,
                                            get_diff_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(ExtraDataListMixin, ReviewRequestChildListMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DiffResource list APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'review-requests/<id>/diffs/'
@@ -344,9 +342,8 @@ class ResourceListTests(ExtraDataListMixin, ReviewRequestChildListMixin,
         self.assertEqual(list(draft.target_groups.all()), [])
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(ExtraDataItemMixin, ReviewRequestChildItemMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DiffResource item APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'review-requests/<id>/diffs/<revision>/'
diff --git a/reviewboard/webapi/tests/test_diff_context.py b/reviewboard/webapi/tests/test_diff_context.py
index 33445f27bbebd2b81a4fe1c84484ab7cc4d730e5..f49bc8839c5b5b66cd2c6a4caeec4122a72c3063 100644
--- a/reviewboard/webapi/tests/test_diff_context.py
+++ b/reviewboard/webapi/tests/test_diff_context.py
@@ -2,7 +2,6 @@
 
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.webapi.testing.decorators import webapi_test_template
 
 from reviewboard.webapi.resources import resources
@@ -13,8 +12,8 @@ from reviewboard.webapi.tests.mixins import (BaseReviewRequestChildMixin,
 from reviewboard.webapi.tests.urls import get_diff_context_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(BaseWebAPITestCase, BaseReviewRequestChildMixin):
+class ResourceTests(BaseWebAPITestCase, BaseReviewRequestChildMixin,
+                    metaclass=BasicTestsMetaclass):
     """Testing the DiffContextResource APIs."""
 
     resource = resources.diff_context
diff --git a/reviewboard/webapi/tests/test_diff_file_attachment.py b/reviewboard/webapi/tests/test_diff_file_attachment.py
index 2bf849a99ef994ef715ba643cafc274f3b31dc89..81801b3ee33f099a7d3d647fb3598443558d12a0 100644
--- a/reviewboard/webapi/tests/test_diff_file_attachment.py
+++ b/reviewboard/webapi/tests/test_diff_file_attachment.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.webapi.errors import PERMISSION_DENIED
 
 from reviewboard.webapi.resources import resources
@@ -13,8 +12,7 @@ from reviewboard.webapi.tests.urls import (get_diff_file_attachment_item_url,
                                            get_diff_file_attachment_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DiffFileAttachmentResource list APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'repositories/<id>/diff-file-attachments/'
@@ -160,8 +158,7 @@ class ResourceListTests(BaseWebAPITestCase):
         self.assertEqual(attachment_rsp['mimetype'], 'image/png')
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DiffFileAttachmentResource item APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'repositories/<id>/diff-file-attachments/<id>/'
diff --git a/reviewboard/webapi/tests/test_diffcommit.py b/reviewboard/webapi/tests/test_diffcommit.py
index 2dffd90cf3a3aec7c88adbf72b1d3fef71e6087c..a02d058e0da10bd7cc9bb76bbb04863a059110ff 100644
--- a/reviewboard/webapi/tests/test_diffcommit.py
+++ b/reviewboard/webapi/tests/test_diffcommit.py
@@ -3,7 +3,6 @@
 from __future__ import unicode_literals
 
 from django.contrib.auth.models import User
-from django.utils import six
 from djblets.features.testing import override_feature_checks
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.errors import PERMISSION_DENIED
@@ -47,8 +46,8 @@ def compare_diffcommit(self, item_rsp, item):
     self.assertEqual(item_rsp['committer_email'], item.committer_email)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase):
+class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Tests for DiffCommitResource list resource."""
 
     fixtures = ['test_users', 'test_scmtools']
@@ -104,9 +103,8 @@ class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase):
                 items)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(ExtraDataItemMixin, ReviewRequestChildItemMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Tests for DiffCommitResource item resource."""
 
     fixtures = ['test_users', 'test_scmtools']
diff --git a/reviewboard/webapi/tests/test_draft_diff.py b/reviewboard/webapi/tests/test_draft_diff.py
index 6beef0e75e604994a9396c9f57555da51132f9c9..26c81d1dbd04ae02fbbf70552cdf142379c96eaf 100644
--- a/reviewboard/webapi/tests/test_draft_diff.py
+++ b/reviewboard/webapi/tests/test_draft_diff.py
@@ -28,8 +28,8 @@ from reviewboard.webapi.tests.urls import (get_draft_diff_item_url,
                                            get_draft_diff_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase):
+class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the DraftDiffResource list APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'review-requests/<id>/draft/diffs/'
@@ -272,8 +272,8 @@ class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase):
         self.assertEqual(list(draft.target_groups.all()), [group])
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(SpyAgency, ExtraDataItemMixin, BaseWebAPITestCase):
+class ResourceItemTests(SpyAgency, ExtraDataItemMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the DraftDiffResource item APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'review-requests/<id>/draft/diffs/<revision>/'
diff --git a/reviewboard/webapi/tests/test_draft_diffcommit.py b/reviewboard/webapi/tests/test_draft_diffcommit.py
index c7768ed9cde79f07dd003572c0c9cf3b02f0545c..2d8bf3c90514c1004925b17375cd9a44d483f852 100644
--- a/reviewboard/webapi/tests/test_draft_diffcommit.py
+++ b/reviewboard/webapi/tests/test_draft_diffcommit.py
@@ -3,7 +3,7 @@
 from __future__ import unicode_literals
 
 from django.core.files.uploadedfile import SimpleUploadedFile
-from django.utils import six, timezone
+from django.utils import timezone
 from djblets.features.testing import override_feature_checks
 from djblets.webapi.errors import INVALID_ATTRIBUTE, INVALID_FORM_DATA
 from djblets.webapi.testing.decorators import webapi_test_template
@@ -24,8 +24,7 @@ from reviewboard.webapi.tests.urls import (get_draft_diffcommit_item_url,
                                            get_draft_diffcommit_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Tests for DraftDiffCommitResource list resource."""
 
     fixtures = ['test_users', 'test_scmtools']
@@ -472,8 +471,8 @@ class ResourceListTests(BaseWebAPITestCase):
             })
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase):
+class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Tests for DraftDiffCommitResource item resource."""
 
     fixtures = ['test_users', 'test_scmtools']
diff --git a/reviewboard/webapi/tests/test_draft_filediff.py b/reviewboard/webapi/tests/test_draft_filediff.py
index e98461cd1abd3bae57fb65d8f366f0e6c9b1cfdb..5f593594081f5c82d8e8e1213bd76b99c37937aa 100644
--- a/reviewboard/webapi/tests/test_draft_filediff.py
+++ b/reviewboard/webapi/tests/test_draft_filediff.py
@@ -3,7 +3,6 @@ from __future__ import unicode_literals
 import os
 
 from django.core.files.uploadedfile import SimpleUploadedFile
-from django.utils import six
 from djblets.webapi.errors import INVALID_FORM_DATA
 from djblets.webapi.testing.decorators import webapi_test_template
 
@@ -22,8 +21,7 @@ from reviewboard.webapi.tests.urls import (get_diff_list_url,
                                            get_draft_filediff_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DraftFileDiffResource list APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'review-requests/<id>/draft/diffs/<revision>/files/'
@@ -133,8 +131,8 @@ class ResourceListTests(BaseWebAPITestCase):
         self.assertEqual(rsp['total_results'], 0)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase):
+class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the DraftFileDiffResource item APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'review-requests/<id>/draft/diffs/<revision>/files/<id>/'
diff --git a/reviewboard/webapi/tests/test_draft_original_file.py b/reviewboard/webapi/tests/test_draft_original_file.py
index f544a87da2766789ab9d2767fef17d1f6c12f58b..2ffdd7fae04459ae60d22ba21fa27f1e07003d27 100644
--- a/reviewboard/webapi/tests/test_draft_original_file.py
+++ b/reviewboard/webapi/tests/test_draft_original_file.py
@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 from django.contrib.auth.models import User
-from django.utils import six
 from djblets.webapi.errors import DOES_NOT_EXIST, PERMISSION_DENIED
 
 from reviewboard.scmtools.core import PRE_CREATION
@@ -12,8 +11,7 @@ from reviewboard.webapi.tests.mixins import BasicTestsMetaclass
 from reviewboard.webapi.tests.urls import get_draft_original_file_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(BaseWebAPITestCase):
+class ResourceTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DraftOriginalFileResource APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = \
diff --git a/reviewboard/webapi/tests/test_draft_patched_file.py b/reviewboard/webapi/tests/test_draft_patched_file.py
index 0cd612aa2dd653a58f36f815c85fa995342aa885..8492ca46af8d8d804275b811e13053587102d5bf 100644
--- a/reviewboard/webapi/tests/test_draft_patched_file.py
+++ b/reviewboard/webapi/tests/test_draft_patched_file.py
@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 from django.contrib.auth.models import User
-from django.utils import six
 from djblets.webapi.errors import DOES_NOT_EXIST, PERMISSION_DENIED
 
 from reviewboard.diffviewer.models import FileDiff
@@ -12,8 +11,7 @@ from reviewboard.webapi.tests.mixins import BasicTestsMetaclass
 from reviewboard.webapi.tests.urls import get_draft_patched_file_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(BaseWebAPITestCase):
+class ResourceTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DraftPatchedFileResource APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = \
diff --git a/reviewboard/webapi/tests/test_file_attachment.py b/reviewboard/webapi/tests/test_file_attachment.py
index 0d946cc9f56a9ed677f0460f4e65a1820921fede..93b2ec626d87900c9904c6309fcb2880c84d9aeb 100644
--- a/reviewboard/webapi/tests/test_file_attachment.py
+++ b/reviewboard/webapi/tests/test_file_attachment.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.webapi.errors import INVALID_FORM_DATA, PERMISSION_DENIED
 
 from reviewboard.attachments.models import (FileAttachment,
@@ -16,8 +15,8 @@ from reviewboard.webapi.tests.urls import (get_file_attachment_item_url,
                                            get_file_attachment_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase):
+class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the FileAttachmentResource list APIs."""
     fixtures = ['test_users']
     basic_get_fixtures = ['test_scmtools']
@@ -203,8 +202,8 @@ class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase):
             self.assertEqual(history.latest_revision, 0)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(ReviewRequestChildItemMixin, BaseWebAPITestCase):
+class ResourceItemTests(ReviewRequestChildItemMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the FileAttachmentResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/file-attachments/<id>/'
diff --git a/reviewboard/webapi/tests/test_file_attachment_comment.py b/reviewboard/webapi/tests/test_file_attachment_comment.py
index 02c258394bd12f3aef3248de5556000f687c79f2..e14425bc79b4096e8edc952f95c10df381695f0f 100644
--- a/reviewboard/webapi/tests/test_file_attachment_comment.py
+++ b/reviewboard/webapi/tests/test_file_attachment_comment.py
@@ -1,7 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
-
 from reviewboard.webapi.resources import resources
 from reviewboard.webapi.tests.base import BaseWebAPITestCase
 from reviewboard.webapi.tests.mimetypes import \
@@ -11,8 +9,8 @@ from reviewboard.webapi.tests.mixins import (BasicTestsMetaclass,
 from reviewboard.webapi.tests.urls import get_file_attachment_comment_list_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase):
+class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the FileAttachmentCommentResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/file-attachments/<id>/comments/'
diff --git a/reviewboard/webapi/tests/test_file_attachment_draft.py b/reviewboard/webapi/tests/test_file_attachment_draft.py
index 9c3b06397e7ea5fde5426f44869882ffc9d08259..cc0ab5ad227bb9c8c96bd650c26e2e51644a0c75 100644
--- a/reviewboard/webapi/tests/test_file_attachment_draft.py
+++ b/reviewboard/webapi/tests/test_file_attachment_draft.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.errors import PERMISSION_DENIED
 
@@ -15,8 +14,7 @@ from reviewboard.webapi.tests.urls import (get_draft_file_attachment_item_url,
                                            get_draft_file_attachment_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DraftFileAttachmentResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/draft/file-attachments/'
@@ -146,8 +144,7 @@ class ResourceListTests(BaseWebAPITestCase):
         self.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DraftFileAttachmentResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/draft/file-attachments/<id>/'
diff --git a/reviewboard/webapi/tests/test_file_diff_comment.py b/reviewboard/webapi/tests/test_file_diff_comment.py
index 2920c0fae946d95ca56164f33e8fda45d7edd244..c54300e594cd4380771a7e20974190497c5ea165 100644
--- a/reviewboard/webapi/tests/test_file_diff_comment.py
+++ b/reviewboard/webapi/tests/test_file_diff_comment.py
@@ -1,7 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
-
 from reviewboard.webapi.resources import resources
 from reviewboard.webapi.tests.base import BaseWebAPITestCase
 from reviewboard.webapi.tests.mimetypes import filediff_comment_list_mimetype
@@ -10,8 +8,8 @@ from reviewboard.webapi.tests.mixins import (BasicTestsMetaclass,
 from reviewboard.webapi.tests.urls import get_filediff_comment_list_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase):
+class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the FileDiffCommentResource list APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = \
diff --git a/reviewboard/webapi/tests/test_filediff.py b/reviewboard/webapi/tests/test_filediff.py
index 210cd4c62dcbedd68137fb7b41caed8b1eb877c1..cc4b4631513d5d049b126c867536d91646480373 100644
--- a/reviewboard/webapi/tests/test_filediff.py
+++ b/reviewboard/webapi/tests/test_filediff.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.features.testing import override_feature_check
 from djblets.webapi.testing.decorators import webapi_test_template
 
@@ -28,8 +27,8 @@ def _compare_item(self, item_rsp, filediff):
     self.assertEqual(item_rsp['status'], filediff.status_string)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase):
+class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the FileDiffResource list APIs."""
 
     resource = resources.filediff
@@ -188,9 +187,8 @@ class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase):
                                 cumulative_filediff.pk)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(ExtraDataItemMixin, ReviewRequestChildItemMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the FileDiffResource item APIs."""
 
     resource = resources.filediff
diff --git a/reviewboard/webapi/tests/test_hosting_service.py b/reviewboard/webapi/tests/test_hosting_service.py
index e34a14af63c5afdd78f80d8e6f044d837d942965..8c814099fcc073e6015ae8a9cbfd654687b996a2 100644
--- a/reviewboard/webapi/tests/test_hosting_service.py
+++ b/reviewboard/webapi/tests/test_hosting_service.py
@@ -72,8 +72,7 @@ def _compare_item(self, item_rsp, hosting_service):
     self.assertEqual(item_rsp['links']['repositories']['href'], accounts_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the HostingServiceResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = 'hosting-services/'
@@ -95,8 +94,7 @@ class ResourceListTests(BaseWebAPITestCase):
                 get_hosting_services())
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the HostingServiceResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = 'hosting-services/<id>/'
diff --git a/reviewboard/webapi/tests/test_hosting_service_account.py b/reviewboard/webapi/tests/test_hosting_service_account.py
index 4ba838f934e528c01607e3f9248ff679b6c61240..e58ec4b204850631857012037d9caf1217d6bba3 100644
--- a/reviewboard/webapi/tests/test_hosting_service_account.py
+++ b/reviewboard/webapi/tests/test_hosting_service_account.py
@@ -1,7 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
-
 from reviewboard.hostingsvcs.models import HostingServiceAccount
 from reviewboard.webapi.resources import resources
 from reviewboard.webapi.tests.base import BaseWebAPITestCase
@@ -20,8 +18,7 @@ def _compare_item(self, item_rsp, account):
     self.assertEqual(item_rsp['service'], account.service.hosting_service_id)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the HostingServiceAccountResource list APIs."""
     sample_api_url = 'hosting-services-accounts/'
     resource = resources.hosting_service_account
@@ -119,8 +116,7 @@ class ResourceListTests(BaseWebAPITestCase):
             pk=rsp['hosting_service_account']['id'])
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the HostingServiceAccountResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = 'hosting-service-accounts/<id>/'
diff --git a/reviewboard/webapi/tests/test_oauth_app.py b/reviewboard/webapi/tests/test_oauth_app.py
index 105b2a602f46cb66104e64e7650046a539042e3a..bb96725be3665723c7c4548464df86633bbfc2a8 100644
--- a/reviewboard/webapi/tests/test_oauth_app.py
+++ b/reviewboard/webapi/tests/test_oauth_app.py
@@ -3,7 +3,6 @@
 from __future__ import unicode_literals
 
 from django.contrib.auth.models import User
-from django.utils import six
 from djblets.db.query import get_object_or_none
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.errors import DOES_NOT_EXIST
@@ -42,8 +41,8 @@ def _compare_item(self, item_rsp, app):
     self.assertEqual(item_rsp['links']['user']['title'], app.user.username)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase):
+class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the OAuthApplicationResource list APIs."""
 
     resource = resources.oauth_app
@@ -572,8 +571,8 @@ class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase):
             self.assertIn('redirect_uris', rsp['fields'])
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase):
+class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the OAuthApplicationResource item APIs."""
 
     resource = resources.oauth_app
diff --git a/reviewboard/webapi/tests/test_oauth_token.py b/reviewboard/webapi/tests/test_oauth_token.py
index 7330c58d2d0cb9e7ec7010f6fe5cfa6581665f15..748c8343fc06ebd2ac3d06770aea8f7054f8471a 100644
--- a/reviewboard/webapi/tests/test_oauth_token.py
+++ b/reviewboard/webapi/tests/test_oauth_token.py
@@ -2,7 +2,6 @@
 
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.db.query import get_object_or_none
 from djblets.features.testing import override_feature_check
 from djblets.testing.decorators import add_fixtures
@@ -27,8 +26,7 @@ def _compare_item(self, item_rsp, access_token):
     self.assertEqual(item_rsp['token'], access_token.token)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the OAuthTokenResource list APIs."""
 
     fixtures = ['test_users']
@@ -95,8 +93,7 @@ class ResourceListTests(BaseWebAPITestCase):
         self.compare_item(rsp['oauth_tokens'][0], tokens[0])
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the OAuthTokenResource item APIs."""
 
     fixtures = ['test_users']
diff --git a/reviewboard/webapi/tests/test_original_file.py b/reviewboard/webapi/tests/test_original_file.py
index e65b9d15055fcb5c919cf4532e92da03e86b8fc7..aea46c333b7876f13bec1041871665fd4185308c 100644
--- a/reviewboard/webapi/tests/test_original_file.py
+++ b/reviewboard/webapi/tests/test_original_file.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.webapi.errors import DOES_NOT_EXIST
 
 from reviewboard.scmtools.core import PRE_CREATION
@@ -12,8 +11,8 @@ from reviewboard.webapi.tests.mixins import (BasicTestsMetaclass,
 from reviewboard.webapi.tests.urls import get_original_file_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(ReviewRequestChildItemMixin, BaseWebAPITestCase):
+class ResourceTests(ReviewRequestChildItemMixin, BaseWebAPITestCase,
+                    metaclass=BasicTestsMetaclass):
     """Testing the OriginalFileResource APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = \
diff --git a/reviewboard/webapi/tests/test_patched_file.py b/reviewboard/webapi/tests/test_patched_file.py
index ca4e21d1090bbb7e44ffce2b7959fb6f963eab6c..9b84740e5fa26cd78ff97dc80fce98fcdc5b1b21 100644
--- a/reviewboard/webapi/tests/test_patched_file.py
+++ b/reviewboard/webapi/tests/test_patched_file.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.webapi.errors import DOES_NOT_EXIST
 
 from reviewboard.diffviewer.models import FileDiff
@@ -12,8 +11,8 @@ from reviewboard.webapi.tests.mixins import (BasicTestsMetaclass,
 from reviewboard.webapi.tests.urls import get_patched_file_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(ReviewRequestChildItemMixin, BaseWebAPITestCase):
+class ResourceTests(ReviewRequestChildItemMixin, BaseWebAPITestCase,
+                    metaclass=BasicTestsMetaclass):
     """Testing the PatchedFileResource APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'review-requests/<id>/diffs/<id>/files/<id>/patched-file/'
diff --git a/reviewboard/webapi/tests/test_remote_repository.py b/reviewboard/webapi/tests/test_remote_repository.py
index 08645de7cdcbf0b1fe2bb78fe02daad4deca91ad..308b9b320aeefcf4d35a1a2c2038ec34ffe1dc96 100644
--- a/reviewboard/webapi/tests/test_remote_repository.py
+++ b/reviewboard/webapi/tests/test_remote_repository.py
@@ -2,7 +2,6 @@ from __future__ import unicode_literals
 
 import json
 
-from django.utils import six
 from kgb import SpyAgency
 
 from reviewboard.hostingsvcs.github import GitHub
@@ -41,8 +40,8 @@ class RemoteRepositoryTestPaginator(APIPaginator):
         }
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(SpyAgency, BaseWebAPITestCase):
+class ResourceListTests(SpyAgency, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the RemoteRepositoryResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = 'hosting-service-accounts/<id>/remote-repositories/'
@@ -103,8 +102,8 @@ class ResourceListTests(SpyAgency, BaseWebAPITestCase):
                 remote_repositories)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(SpyAgency, BaseWebAPITestCase):
+class ResourceItemTests(SpyAgency, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the RemoteRepositoryResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = 'hosting-service-accounts/<id>/remote-repositories/<id>/'
diff --git a/reviewboard/webapi/tests/test_repository.py b/reviewboard/webapi/tests/test_repository.py
index f223dfb4925d349a3b54862d8b8bd53eaf0c5e52..48da02a4996d54f7e29023cc19d9482291f6feaa 100644
--- a/reviewboard/webapi/tests/test_repository.py
+++ b/reviewboard/webapi/tests/test_repository.py
@@ -4,7 +4,6 @@ import os
 
 import kgb
 import paramiko
-from django.utils import six
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.testing.decorators import webapi_test_template
 from kgb import SpyAgency
@@ -117,8 +116,8 @@ class BaseRepositoryTests(SpyAgency, BaseWebAPITestCase):
         return repository
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ExtraDataListMixin, BaseRepositoryTests):
+class ResourceListTests(ExtraDataListMixin, BaseRepositoryTests,
+                        metaclass=BasicTestsMetaclass):
     """Testing the RepositoryResource list APIs."""
 
     sample_api_url = 'repositories/'
@@ -902,8 +901,8 @@ class ResourceListTests(ExtraDataListMixin, BaseRepositoryTests):
             expected_mimetype=expected_mimetype)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(ExtraDataItemMixin, BaseRepositoryTests):
+class ResourceItemTests(ExtraDataItemMixin, BaseRepositoryTests,
+                        metaclass=BasicTestsMetaclass):
     """Testing the RepositoryResource item APIs."""
 
     sample_api_url = 'repositories/<id>/'
diff --git a/reviewboard/webapi/tests/test_repository_branches.py b/reviewboard/webapi/tests/test_repository_branches.py
index dcf409f7153642d9d5b9827b466062f5330560b3..81e3ee4829818c4cb9b41c9197ef7866ca001455 100644
--- a/reviewboard/webapi/tests/test_repository_branches.py
+++ b/reviewboard/webapi/tests/test_repository_branches.py
@@ -1,7 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
-
 from reviewboard.webapi.errors import REPO_NOT_IMPLEMENTED
 from reviewboard.webapi.resources import resources
 from reviewboard.webapi.tests.base import BaseWebAPITestCase
@@ -12,8 +10,7 @@ from reviewboard.webapi.tests.urls import get_repository_branches_url
 import nose
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(BaseWebAPITestCase):
+class ResourceTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the RepositoryBranchesResource list APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'repositories/<id>/branches/'
diff --git a/reviewboard/webapi/tests/test_repository_commits.py b/reviewboard/webapi/tests/test_repository_commits.py
index 1a29f45aa872f7efe84c52703a66a738b7d83599..4c3f593e7da59aadd1920d3108999a5b3141615e 100644
--- a/reviewboard/webapi/tests/test_repository_commits.py
+++ b/reviewboard/webapi/tests/test_repository_commits.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.testing.decorators import add_fixtures
 
 from reviewboard.webapi.resources import resources
@@ -12,8 +11,7 @@ from reviewboard.webapi.tests.urls import get_repository_commits_url
 import nose
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(BaseWebAPITestCase):
+class ResourceTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the RepositoryCommitsResource APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'repositories/<id>/commits/'
diff --git a/reviewboard/webapi/tests/test_repository_info.py b/reviewboard/webapi/tests/test_repository_info.py
index 868519e25da05cb3ed339ade6a28faa55e46378f..a210468b3d871f1c783a7d43a10a12006f851a25 100644
--- a/reviewboard/webapi/tests/test_repository_info.py
+++ b/reviewboard/webapi/tests/test_repository_info.py
@@ -1,7 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
-
 from reviewboard.webapi.resources import resources
 from reviewboard.webapi.tests.base import BaseWebAPITestCase
 from reviewboard.webapi.tests.mimetypes import repository_info_item_mimetype
@@ -9,8 +7,7 @@ from reviewboard.webapi.tests.mixins import BasicTestsMetaclass
 from reviewboard.webapi.tests.urls import get_repository_info_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(BaseWebAPITestCase):
+class ResourceTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the RepositoryInfoResource APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'repositories/<id>/info/'
diff --git a/reviewboard/webapi/tests/test_review.py b/reviewboard/webapi/tests/test_review.py
index 3a24d27c13abf82ab869c872b4e49adef637ae61..965a17a33feba9552769cec696ecfad8dad14c66 100644
--- a/reviewboard/webapi/tests/test_review.py
+++ b/reviewboard/webapi/tests/test_review.py
@@ -3,7 +3,7 @@ from __future__ import unicode_literals
 from datetime import datetime, timedelta
 
 from django.core import mail
-from django.utils import six, timezone
+from django.utils import timezone
 from djblets.util.dates import get_tz_aware_utcnow
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.errors import (DOES_NOT_EXIST, INVALID_FORM_DATA,
@@ -27,9 +27,8 @@ from reviewboard.webapi.tests.urls import (get_review_item_url,
                                            get_review_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(ReviewListMixin, ReviewRequestChildListMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/reviews/'
@@ -134,9 +133,9 @@ class ResourceListTests(ReviewListMixin, ReviewRequestChildListMixin,
         self.compare_item(rsp['review'], review)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(SpyAgency, ReviewItemMixin,
-                        ReviewRequestChildItemMixin, BaseWebAPITestCase):
+                        ReviewRequestChildItemMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the ReviewResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/reviews/<id>/'
diff --git a/reviewboard/webapi/tests/test_review_comment.py b/reviewboard/webapi/tests/test_review_comment.py
index 50353efa3155c78b24df212aad078b0889d6ce17..4ce2fda62b76768be4d1dfbb692ea20bdfd06545 100644
--- a/reviewboard/webapi/tests/test_review_comment.py
+++ b/reviewboard/webapi/tests/test_review_comment.py
@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 from django.contrib.auth.models import User
-from django.utils import six
 from djblets.features.testing import override_feature_check
 from djblets.webapi.errors import INVALID_FORM_DATA, PERMISSION_DENIED
 from djblets.webapi.testing.decorators import webapi_test_template
@@ -120,9 +119,9 @@ def _compare_item(self, item_rsp, comment):
         self.assertEqual(item_rsp['text_type'], 'plain')
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(SpyAgency, CommentListMixin,
-                        ReviewRequestChildListMixin, BaseResourceTestCase):
+                        ReviewRequestChildListMixin, BaseResourceTestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the ReviewDiffCommentResource list APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'review-requests/<id>/reviews/<id>/diff-comments/'
@@ -841,9 +840,9 @@ class ResourceListTests(SpyAgency, CommentListMixin,
 
         self.assertTrue(FileDiff.get_ancestors.called)
 
-@six.add_metaclass(BasicTestsMetaclass)
+
 class ResourceItemTests(CommentItemMixin, ReviewRequestChildItemMixin,
-                        BaseResourceTestCase):
+                        BaseResourceTestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewDiffCommentResource item APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'review-requests/<id>/reviews/<id>/diff-comments/'
diff --git a/reviewboard/webapi/tests/test_review_general_comment.py b/reviewboard/webapi/tests/test_review_general_comment.py
index 3d1c470e604bd169ee506b6d5d2fe4013bb046eb..fc58ba7de0c7c3a71f33dbf6c2ba3aa283442321 100644
--- a/reviewboard/webapi/tests/test_review_general_comment.py
+++ b/reviewboard/webapi/tests/test_review_general_comment.py
@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 from django.contrib.auth.models import User
-from django.utils import six
 from djblets.webapi.errors import PERMISSION_DENIED
 from djblets.webapi.testing.decorators import webapi_test_template
 
@@ -49,9 +48,8 @@ class BaseTestCase(BaseWebAPITestCase):
         return comment, review, review_request
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(CommentListMixin, ReviewRequestChildListMixin,
-                        BaseTestCase):
+                        BaseTestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewGeneralCommentResource list APIs."""
     sample_api_url = 'review-requests/<id>/reviews/<id>/general-comments/'
     resource = resources.review_general_comment
@@ -158,9 +156,9 @@ class ResourceListTests(CommentListMixin, ReviewRequestChildListMixin,
         self.assertEqual(rsp['stat'], 'fail')
         self.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)
 
-@six.add_metaclass(BasicTestsMetaclass)
+
 class ResourceItemTests(CommentItemMixin, ReviewRequestChildItemMixin,
-                        BaseTestCase):
+                        BaseTestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewGeneralCommentResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = \
diff --git a/reviewboard/webapi/tests/test_review_group.py b/reviewboard/webapi/tests/test_review_group.py
index f44867d3d025dcebefacee570d0696d135df5ae0..d41541e940826862f65f8c33e6e982326454e1a0 100644
--- a/reviewboard/webapi/tests/test_review_group.py
+++ b/reviewboard/webapi/tests/test_review_group.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.db.query import get_object_or_none
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.errors import PERMISSION_DENIED
@@ -19,8 +18,8 @@ from reviewboard.webapi.tests.urls import (get_review_group_item_url,
                                            get_review_group_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase):
+class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the ReviewGroupResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = 'groups/'
@@ -162,8 +161,8 @@ class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase):
         self.assertEqual(rsp['err']['code'], GROUP_ALREADY_EXISTS.code)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase):
+class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the ReviewGroupResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = 'groups/<id>/'
diff --git a/reviewboard/webapi/tests/test_review_group_user.py b/reviewboard/webapi/tests/test_review_group_user.py
index 7429b5c2d07442462d5fa9c8279b24fbb99e69c6..5f6da1a26b96cb12dc36a7d7112a507d40474d22 100644
--- a/reviewboard/webapi/tests/test_review_group_user.py
+++ b/reviewboard/webapi/tests/test_review_group_user.py
@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 from django.contrib.auth.models import User
-from django.utils import six
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.errors import PERMISSION_DENIED
 from djblets.webapi.testing.decorators import webapi_test_template
@@ -17,8 +16,7 @@ from reviewboard.webapi.tests.urls import (get_review_group_user_item_url,
                                            get_user_item_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewGroupUserResource list API tests."""
     fixtures = ['test_users']
     sample_api_url = 'groups/<name>/users/'
@@ -210,8 +208,7 @@ class ResourceListTests(BaseWebAPITestCase):
         self.assertEqual(group.users.count(), 0)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewGroupUserResource item API tests."""
     fixtures = ['test_users']
     sample_api_url = 'groups/<name>/users/<username>/'
diff --git a/reviewboard/webapi/tests/test_review_reply.py b/reviewboard/webapi/tests/test_review_reply.py
index 63f8f9d8f46bd1f6efc67892e5f876b308c5e53c..eb9f83f71b428f527901a99f6ffd0e8e80097e4b 100644
--- a/reviewboard/webapi/tests/test_review_reply.py
+++ b/reviewboard/webapi/tests/test_review_reply.py
@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 from django.core import mail
-from django.utils import six
 
 from reviewboard.reviews.models import Review
 from reviewboard.webapi.resources import resources
@@ -31,9 +30,8 @@ class BaseResourceTestCase(BaseWebAPITestCase):
         return review
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(ReviewListMixin, ReviewRequestChildListMixin,
-                        BaseResourceTestCase):
+                        BaseResourceTestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewReplyResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/reviews/<id>/replies/'
@@ -155,9 +153,8 @@ class ResourceListTests(ReviewListMixin, ReviewRequestChildListMixin,
         self.assertEqual(reply.body_bottom, body_bottom)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(ReviewItemMixin, ReviewRequestChildItemMixin,
-                        BaseResourceTestCase):
+                        BaseResourceTestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewReplyResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/reviews/<id>/replies/<id>/'
diff --git a/reviewboard/webapi/tests/test_review_reply_diff_comment.py b/reviewboard/webapi/tests/test_review_reply_diff_comment.py
index c9207542473c7ec73d716e3a7f8b5eceadc46ad0..573ffdd0e94019940e7ec3bb5f2596c4d242d1d9 100644
--- a/reviewboard/webapi/tests/test_review_reply_diff_comment.py
+++ b/reviewboard/webapi/tests/test_review_reply_diff_comment.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 
 from reviewboard.reviews.models import Comment
 from reviewboard.webapi.resources import resources
@@ -20,9 +19,8 @@ from reviewboard.webapi.tests.urls import (
     get_review_reply_diff_comment_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(CommentReplyListMixin, ReviewRequestChildListMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewReplyDiffCommentResource list APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = \
@@ -149,9 +147,8 @@ class ResourceListTests(CommentReplyListMixin, ReviewRequestChildListMixin,
         self.assertEqual(reply_comment.text, comment_text)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(CommentReplyItemMixin, ReviewRequestChildItemMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewReplyDiffCommentResource item APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = \
diff --git a/reviewboard/webapi/tests/test_review_reply_file_attachment_comment.py b/reviewboard/webapi/tests/test_review_reply_file_attachment_comment.py
index 9a44c6c93f67458c038093f8302d3d799c18ecf5..c28d56d62d41b3bd5b36d0abc3050f60af31f56f 100644
--- a/reviewboard/webapi/tests/test_review_reply_file_attachment_comment.py
+++ b/reviewboard/webapi/tests/test_review_reply_file_attachment_comment.py
@@ -1,7 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
-
 from reviewboard.reviews.models import FileAttachmentComment
 from reviewboard.webapi.resources import resources
 from reviewboard.webapi.tests.base import BaseWebAPITestCase
@@ -20,9 +18,8 @@ from reviewboard.webapi.tests.urls import (
     get_review_reply_file_attachment_comment_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(CommentReplyListMixin, ReviewRequestChildListMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewReplyFileAttachmentCommentResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = ('review-requests/<id>/reviews/<id>/replies/<id>/'
@@ -173,9 +170,8 @@ class ResourceListTests(CommentReplyListMixin, ReviewRequestChildListMixin,
         self.check_post_result(self.user, rsp, reply, comment, file_attachment)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(CommentReplyItemMixin, ReviewRequestChildItemMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewReplyFileAttachmentCommentResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = ('review-requests/<id>/reviews/<id>/replies/<id>/'
diff --git a/reviewboard/webapi/tests/test_review_reply_general_comment.py b/reviewboard/webapi/tests/test_review_reply_general_comment.py
index 844b0cab254c79f59372cb90baf71506066bae65..0556dc87e679bea8ed23a02eaf7f50b3b2e76911 100644
--- a/reviewboard/webapi/tests/test_review_reply_general_comment.py
+++ b/reviewboard/webapi/tests/test_review_reply_general_comment.py
@@ -1,7 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
-
 from reviewboard.reviews.models import GeneralComment
 from reviewboard.webapi.resources import resources
 from reviewboard.webapi.tests.base import BaseWebAPITestCase
@@ -20,9 +18,8 @@ from reviewboard.webapi.tests.urls import (
     get_review_reply_general_comment_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(CommentReplyListMixin, ReviewRequestChildListMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewReplyGeneralCommentResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = \
@@ -135,9 +132,8 @@ class ResourceListTests(CommentReplyListMixin, ReviewRequestChildListMixin,
         self.assertEqual(reply_comment.text, comment_text)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(CommentReplyItemMixin, ReviewRequestChildItemMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewReplyGeneralCommentResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = ('review-requests/<id>/reviews/<id>/replies/<id>/'
diff --git a/reviewboard/webapi/tests/test_review_reply_screenshot_comment.py b/reviewboard/webapi/tests/test_review_reply_screenshot_comment.py
index 76f518bad61e508f91592677b02efaac68ece3ff..8c2cf31dd18ab40fda8219d884332abcfb9c217d 100644
--- a/reviewboard/webapi/tests/test_review_reply_screenshot_comment.py
+++ b/reviewboard/webapi/tests/test_review_reply_screenshot_comment.py
@@ -1,7 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
-
 from reviewboard.reviews.models import ScreenshotComment
 from reviewboard.webapi.resources import resources
 from reviewboard.webapi.tests.base import BaseWebAPITestCase
@@ -20,9 +18,8 @@ from reviewboard.webapi.tests.urls import (
     get_review_reply_screenshot_comment_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(CommentReplyListMixin, ReviewRequestChildListMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewReplyScreenshotCommentResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = \
@@ -141,9 +138,8 @@ class ResourceListTests(CommentReplyListMixin, ReviewRequestChildListMixin,
         self.assertEqual(reply_comment.text, comment_text)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(CommentReplyItemMixin, ReviewRequestChildItemMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewReplyScreenshotCommentResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = ('review-requests/<id>/reviews/<id>/replies/<id>/'
diff --git a/reviewboard/webapi/tests/test_review_request.py b/reviewboard/webapi/tests/test_review_request.py
index 5b30e3834d15cbfd5109273b544bde56a9b89a71..722687923c8769fa241e31f3521202512cee7827 100644
--- a/reviewboard/webapi/tests/test_review_request.py
+++ b/reviewboard/webapi/tests/test_review_request.py
@@ -46,8 +46,8 @@ from reviewboard.webapi.tests.urls import (get_repository_item_url,
                                            get_user_item_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(SpyAgency, ExtraDataListMixin, BaseWebAPITestCase):
+class ResourceListTests(SpyAgency, ExtraDataListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the ReviewRequestResource list API tests."""
     fixtures = ['test_users']
     basic_post_fixtures = ['test_scmtools']
@@ -1666,8 +1666,8 @@ class ResourceListTests(SpyAgency, ExtraDataListMixin, BaseWebAPITestCase):
         ReviewRequest.objects.get(pk=rsp['review_request']['id'])
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase):
+class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the ReviewRequestResource item API tests."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/'
diff --git a/reviewboard/webapi/tests/test_review_request_draft.py b/reviewboard/webapi/tests/test_review_request_draft.py
index 80312e0b51e3227dbcddb5caec4ecf4fbc2f41f3..4d2db3ff5883cae962bc94acbb4d0879d67e51ad 100644
--- a/reviewboard/webapi/tests/test_review_request_draft.py
+++ b/reviewboard/webapi/tests/test_review_request_draft.py
@@ -3,7 +3,6 @@ from __future__ import print_function, unicode_literals
 from django.contrib import auth
 from django.contrib.auth.models import Permission, User
 from django.core import mail
-from django.utils import six
 from djblets.features.testing import override_feature_check
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.errors import INVALID_FORM_DATA, PERMISSION_DENIED
@@ -34,9 +33,8 @@ from reviewboard.webapi.tests.mixins_extra_data import (ExtraDataItemMixin,
 from reviewboard.webapi.tests.urls import get_review_request_draft_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceTests(SpyAgency, ExtraDataListMixin, ExtraDataItemMixin,
-                    BaseWebAPITestCase):
+                    BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewRequestDraftResource API tests."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/draft/'
diff --git a/reviewboard/webapi/tests/test_review_request_last_update.py b/reviewboard/webapi/tests/test_review_request_last_update.py
index 1805cbb9ec425a5d47fa26635e25f3f089bab80c..5ec3b5455ca202ef78a807f2a425dec487aff73f 100644
--- a/reviewboard/webapi/tests/test_review_request_last_update.py
+++ b/reviewboard/webapi/tests/test_review_request_last_update.py
@@ -4,7 +4,6 @@ from __future__ import unicode_literals
 
 from dateutil.parser import parse as parse_date
 from django.contrib.auth.models import User
-from django.utils import six
 from djblets.webapi.testing.decorators import webapi_test_template
 
 from reviewboard.diffviewer.models import DiffSet
@@ -18,8 +17,7 @@ from reviewboard.webapi.tests.mixins import BasicTestsMetaclass
 from reviewboard.webapi.tests.urls import get_review_request_last_update_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(BaseWebAPITestCase):
+class ResourceTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing ReviewRequestLastUpdateResource APIs."""
 
     fixtures = ['test_users', 'test_scmtools']
diff --git a/reviewboard/webapi/tests/test_review_screenshot_comment.py b/reviewboard/webapi/tests/test_review_screenshot_comment.py
index 8ff8f24f58405491cf28255f09dc7fc4e5528e6b..98cab2bad7becb5d77b33c01de7f7ffa0e4c8c44 100644
--- a/reviewboard/webapi/tests/test_review_screenshot_comment.py
+++ b/reviewboard/webapi/tests/test_review_screenshot_comment.py
@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 from django.contrib.auth.models import User
-from django.utils import six
 from djblets.webapi.errors import PERMISSION_DENIED
 
 from reviewboard.reviews.models import ScreenshotComment
@@ -50,9 +49,8 @@ class BaseTestCase(BaseWebAPITestCase):
         return comment, review, review_request
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(CommentListMixin, ReviewRequestChildListMixin,
-                        BaseTestCase):
+                        BaseTestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewScreenshotCommentResource list APIs."""
     sample_api_url = 'review-requests/<id>/reviews/<id>/screenshot-comments/'
     resource = resources.review_screenshot_comment
@@ -152,9 +150,8 @@ class ResourceListTests(CommentListMixin, ReviewRequestChildListMixin,
         self.assertTrue(rsp['screenshot_comments'][0]['issue_opened'])
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(CommentItemMixin, ReviewRequestChildItemMixin,
-                        BaseTestCase):
+                        BaseTestCase, metaclass=BasicTestsMetaclass):
     """Testing the ReviewScreenshotCommentResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = \
diff --git a/reviewboard/webapi/tests/test_root.py b/reviewboard/webapi/tests/test_root.py
index 9cb0715770d72668d6956ade1e589e742269b2de..a975796af7b0109aa7bb3c9c56b3bfadcc38a782 100644
--- a/reviewboard/webapi/tests/test_root.py
+++ b/reviewboard/webapi/tests/test_root.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.features.testing import override_feature_check
 from djblets.testing.decorators import add_fixtures
 
@@ -12,8 +11,7 @@ from reviewboard.webapi.tests.mixins import BasicTestsMetaclass
 from reviewboard.webapi.tests.urls import get_root_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(BaseWebAPITestCase):
+class ResourceTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the RootResource APIs."""
     fixtures = ['test_users']
     sample_api_url = '/'
diff --git a/reviewboard/webapi/tests/test_screenshot.py b/reviewboard/webapi/tests/test_screenshot.py
index 4706c7dc9375ce894979cc2ab7399d8ce9dfed9e..9ad480958cf7efeb0698a2a4866f26bd214a1406 100644
--- a/reviewboard/webapi/tests/test_screenshot.py
+++ b/reviewboard/webapi/tests/test_screenshot.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.webapi.errors import PERMISSION_DENIED
 
 from reviewboard.webapi.resources import resources
@@ -14,8 +13,8 @@ from reviewboard.webapi.tests.urls import (get_screenshot_list_url,
                                            get_screenshot_item_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase):
+class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the ScreenshotResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/screenshots/'
@@ -110,8 +109,8 @@ class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase):
         self.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(ReviewRequestChildItemMixin, BaseWebAPITestCase):
+class ResourceItemTests(ReviewRequestChildItemMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the ScreenshotResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/screenshots/<id>/'
diff --git a/reviewboard/webapi/tests/test_screenshot_comment.py b/reviewboard/webapi/tests/test_screenshot_comment.py
index 0cb7bd96337628849c4a476ce58cc2e4f634095c..76c77ba507e1d38b060f4afb437e9063965f91b1 100644
--- a/reviewboard/webapi/tests/test_screenshot_comment.py
+++ b/reviewboard/webapi/tests/test_screenshot_comment.py
@@ -1,7 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
-
 from reviewboard.webapi.resources import resources
 from reviewboard.webapi.tests.base import BaseWebAPITestCase
 from reviewboard.webapi.tests.mimetypes import screenshot_comment_list_mimetype
@@ -10,8 +8,8 @@ from reviewboard.webapi.tests.mixins import (BasicTestsMetaclass,
 from reviewboard.webapi.tests.urls import get_screenshot_comment_list_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase):
+class ResourceListTests(ReviewRequestChildListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the ScreenshotCommentResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/screenshots/<id>/comments/'
diff --git a/reviewboard/webapi/tests/test_screenshot_draft.py b/reviewboard/webapi/tests/test_screenshot_draft.py
index e814e7e2b06e39a834398dfc56ecb909f824d834..1aa1758c9f696bcd3cc6269ed18fce9ff1d2c101 100644
--- a/reviewboard/webapi/tests/test_screenshot_draft.py
+++ b/reviewboard/webapi/tests/test_screenshot_draft.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.webapi.errors import PERMISSION_DENIED
 
 from reviewboard.reviews.models import ReviewRequestDraft, Screenshot
@@ -13,8 +12,7 @@ from reviewboard.webapi.tests.urls import (get_screenshot_draft_item_url,
                                            get_screenshot_draft_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DraftScreenshotResource list APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/draft/screenshots/'
@@ -99,8 +97,7 @@ class ResourceListTests(BaseWebAPITestCase):
         self.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the DraftScreenshotResource item APIs."""
     fixtures = ['test_users']
     sample_api_url = 'review-requests/<id>/draft/screenshots/<id>/'
diff --git a/reviewboard/webapi/tests/test_search.py b/reviewboard/webapi/tests/test_search.py
index 0f704bf23fb42dae7ec15551ac9f104c1c5556a5..7a170da24210cd97d19e09966385b8d999497b67 100644
--- a/reviewboard/webapi/tests/test_search.py
+++ b/reviewboard/webapi/tests/test_search.py
@@ -3,7 +3,6 @@
 from __future__ import unicode_literals
 
 from django.contrib.auth.models import User
-from django.utils import six
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.testing.decorators import webapi_test_template
 from kgb import SpyAgency
@@ -18,8 +17,8 @@ from reviewboard.webapi.tests.mixins import BasicTestsMetaclass
 from reviewboard.webapi.tests.urls import get_search_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(SpyAgency, BaseWebAPITestCase):
+class ResourceTests(SpyAgency, BaseWebAPITestCase,
+                    metaclass=BasicTestsMetaclass):
     """Testing the SearchResource APIs."""
 
     fixtures = ['test_users']
diff --git a/reviewboard/webapi/tests/test_server_info.py b/reviewboard/webapi/tests/test_server_info.py
index 05d2b544167b5d87cd79bdf623f32f7610a346a1..495eae809498ef6d33999792c14986d849cbfa28 100644
--- a/reviewboard/webapi/tests/test_server_info.py
+++ b/reviewboard/webapi/tests/test_server_info.py
@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 from django.conf import settings
-from django.utils import six
 
 from reviewboard import get_version_string, get_package_version, is_release
 from reviewboard.admin.server import get_server_url
@@ -13,8 +12,7 @@ from reviewboard.webapi.tests.mixins import BasicTestsMetaclass
 from reviewboard.webapi.tests.urls import get_server_info_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(BaseWebAPITestCase):
+class ResourceTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the ServerInfoResource APIs."""
 
     fixtures = ['test_users']
diff --git a/reviewboard/webapi/tests/test_session.py b/reviewboard/webapi/tests/test_session.py
index b1e6a805f9b977f8d2460d0416a94f267cc82ff9..310aa4b95fd37bff8279d783d87b3122359fb73c 100644
--- a/reviewboard/webapi/tests/test_session.py
+++ b/reviewboard/webapi/tests/test_session.py
@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 from django.http import SimpleCookie
-from django.utils import six
 from djblets.webapi.errors import NOT_LOGGED_IN
 from djblets.webapi.testing.decorators import webapi_test_template
 
@@ -12,8 +11,7 @@ from reviewboard.webapi.tests.mixins import BasicTestsMetaclass
 from reviewboard.webapi.tests.urls import get_session_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(BaseWebAPITestCase):
+class ResourceTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the SessionResource APIs."""
     fixtures = ['test_users']
     sample_api_url = 'session/'
diff --git a/reviewboard/webapi/tests/test_status_update.py b/reviewboard/webapi/tests/test_status_update.py
index bd0064b21cc47ff6016406ea939f1772a6644c3e..707ecb9da7d0499d3c00cc1b04503c2d628d37ab 100644
--- a/reviewboard/webapi/tests/test_status_update.py
+++ b/reviewboard/webapi/tests/test_status_update.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.features.testing import override_feature_checks
 from djblets.webapi.errors import DOES_NOT_EXIST, INVALID_FORM_DATA
 from djblets.webapi.testing.decorators import webapi_test_template
@@ -23,9 +22,8 @@ from reviewboard.webapi.tests.urls import (get_review_item_url,
                                            get_status_update_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(ExtraDataListMixin, ReviewRequestChildListMixin,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the StatusUpdateResource list APIs."""
 
     fixtures = ['test_users']
@@ -216,9 +214,9 @@ class ResourceListTests(ExtraDataListMixin, ReviewRequestChildListMixin,
         self.assertTrue('review_id' in rsp['fields'])
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(SpyAgency, ReviewRequestChildItemMixin,
-                        ExtraDataItemMixin, BaseWebAPITestCase):
+                        ExtraDataItemMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Testing the StatusUpdateResource item APIs."""
 
     fixtures = ['test_users']
diff --git a/reviewboard/webapi/tests/test_user.py b/reviewboard/webapi/tests/test_user.py
index 8cbdeb212bb764a1fec910da2ce001790d31c7a2..c345d7b4cd49ebc0e565bfa938782372bfec7ce5 100644
--- a/reviewboard/webapi/tests/test_user.py
+++ b/reviewboard/webapi/tests/test_user.py
@@ -3,7 +3,6 @@ from __future__ import unicode_literals
 import logging
 
 from django.contrib.auth.models import Permission, User
-from django.utils import six
 from djblets.avatars.services.base import AvatarService
 from djblets.avatars.services.gravatar import GravatarService
 from djblets.testing.decorators import add_fixtures
@@ -65,9 +64,8 @@ class SimpleRenderAvatarService(NoURLAvatarService):
                                                                 user.username)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceListTests(AvatarServicesTestMixin, SpyAgency,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the UserResource list API tests."""
 
     fixtures = ['test_users']
@@ -418,9 +416,8 @@ class ResourceListTests(AvatarServicesTestMixin, SpyAgency,
             })
 
 
-@six.add_metaclass(BasicTestsMetaclass)
 class ResourceItemTests(AvatarServicesTestMixin, SpyAgency,
-                        BaseWebAPITestCase):
+                        BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the UserResource item API tests."""
     fixtures = ['test_users']
     sample_api_url = 'users/<username>/'
diff --git a/reviewboard/webapi/tests/test_user_file_attachment.py b/reviewboard/webapi/tests/test_user_file_attachment.py
index 51270e7f1530e5db66436e677a3ca45556347836..299b9e6c6aac1ca5e4ab31db8202988a0dbd2cd9 100644
--- a/reviewboard/webapi/tests/test_user_file_attachment.py
+++ b/reviewboard/webapi/tests/test_user_file_attachment.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.webapi.errors import DUPLICATE_ITEM
 
 from reviewboard.attachments.models import FileAttachment
@@ -15,8 +14,7 @@ from reviewboard.webapi.tests.urls import (get_user_file_attachment_item_url,
                                            get_user_file_attachment_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the UserFileAttachmentResource list APIs."""
 
     fixtures = ['test_users', 'test_site']
@@ -107,8 +105,7 @@ class ResourceListTests(BaseWebAPITestCase):
         self.check_post_result(None, rsp, caption)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the UserFileAttachmentResource item APIs."""
 
     fixtures = ['test_users']
diff --git a/reviewboard/webapi/tests/test_validate_diff.py b/reviewboard/webapi/tests/test_validate_diff.py
index d5437f9690b236ae2404e0934c5f88392157ffb7..ba049fbe626de9a6643384824bcbe3df1d0d5ac5 100644
--- a/reviewboard/webapi/tests/test_validate_diff.py
+++ b/reviewboard/webapi/tests/test_validate_diff.py
@@ -3,7 +3,6 @@ from __future__ import unicode_literals
 import os
 
 from django.core.files.uploadedfile import SimpleUploadedFile
-from django.utils import six
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.errors import INVALID_FORM_DATA
 from djblets.webapi.testing.decorators import webapi_test_template
@@ -20,8 +19,8 @@ from reviewboard.webapi.tests.mixins import BasicTestsMetaclass
 from reviewboard.webapi.tests.urls import get_validate_diff_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(SpyAgency, BaseWebAPITestCase):
+class ResourceTests(SpyAgency, BaseWebAPITestCase,
+                    metaclass=BasicTestsMetaclass):
     """Testing the ValidateDiffResource APIs."""
     fixtures = ['test_users', 'test_scmtools']
     sample_api_url = 'validation/diffs/'
diff --git a/reviewboard/webapi/tests/test_validate_diffcommit.py b/reviewboard/webapi/tests/test_validate_diffcommit.py
index 65a1049047824ce1323e71f4c5dfed5e4b9f0b68..d39635052616edd89e1d5d3c2c6674cf0ed3f6d1 100644
--- a/reviewboard/webapi/tests/test_validate_diffcommit.py
+++ b/reviewboard/webapi/tests/test_validate_diffcommit.py
@@ -6,7 +6,6 @@ import base64
 import json
 
 from django.core.files.uploadedfile import SimpleUploadedFile
-from django.utils import six
 from djblets.features.testing import override_feature_checks
 from djblets.webapi.errors import INVALID_ATTRIBUTE
 from djblets.webapi.testing.decorators import webapi_test_template
@@ -23,8 +22,8 @@ from reviewboard.webapi.tests.mixins import BasicTestsMetaclass
 from reviewboard.webapi.tests.urls import get_validate_diffcommit_url
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceTests(SpyAgency, BaseWebAPITestCase):
+class ResourceTests(SpyAgency, BaseWebAPITestCase,
+                    metaclass=BasicTestsMetaclass):
     """Testing ValidateDiffCommitResource API."""
 
     resource = resources.validate_diffcommit
diff --git a/reviewboard/webapi/tests/test_watched_review_group.py b/reviewboard/webapi/tests/test_watched_review_group.py
index 0196d49fb12f23067ec25d1ff6ade7d75c60b6b1..ab3b502ab311637e269e058fb53275b2589dc32a 100644
--- a/reviewboard/webapi/tests/test_watched_review_group.py
+++ b/reviewboard/webapi/tests/test_watched_review_group.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.errors import DOES_NOT_EXIST, PERMISSION_DENIED
 
@@ -16,8 +15,7 @@ from reviewboard.webapi.tests.urls import (
     get_watched_review_group_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the WatchedReviewGroupResource list API tests."""
     fixtures = ['test_users']
     sample_api_url = 'users/<username>/watched/review-groups/'
@@ -98,8 +96,7 @@ class ResourceListTests(BaseWebAPITestCase):
         self.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the WatchedReviewGroupResource item API tests."""
     fixtures = ['test_users']
     test_http_methods = ('DELETE', 'PUT')
diff --git a/reviewboard/webapi/tests/test_watched_review_request.py b/reviewboard/webapi/tests/test_watched_review_request.py
index 81cae0578cdda7efaf1a1213c55341e368e8b905..c7c191cbeaa731decfc250e87912abe1852a7e82 100644
--- a/reviewboard/webapi/tests/test_watched_review_request.py
+++ b/reviewboard/webapi/tests/test_watched_review_request.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.utils import six
 from djblets.testing.decorators import add_fixtures
 from djblets.webapi.errors import DOES_NOT_EXIST, PERMISSION_DENIED
 
@@ -16,8 +15,7 @@ from reviewboard.webapi.tests.urls import (
     get_watched_review_request_list_url)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(BaseWebAPITestCase):
+class ResourceListTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the WatchedReviewRequestResource list API tests."""
     fixtures = ['test_users']
     test_http_methods = ('GET', 'POST')
@@ -119,8 +117,7 @@ class ResourceListTests(BaseWebAPITestCase):
         self.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(BaseWebAPITestCase):
+class ResourceItemTests(BaseWebAPITestCase, metaclass=BasicTestsMetaclass):
     """Testing the WatchedReviewRequestResource item API tests."""
     fixtures = ['test_users']
     test_http_methods = ('DELETE', 'PUT')
diff --git a/reviewboard/webapi/tests/test_webhook.py b/reviewboard/webapi/tests/test_webhook.py
index 3ee54046355b4730b3a2ab96864e7c0eddeaa432..67ac4e0f3943d377a35c3019b4f330c06645333e 100644
--- a/reviewboard/webapi/tests/test_webhook.py
+++ b/reviewboard/webapi/tests/test_webhook.py
@@ -38,8 +38,8 @@ def compare_item(self, item_rsp, webhook):
     self.assertEqual(item_rsp['extra_data'], webhook.extra_data)
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase):
+class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Tests for the WebHookResource list resource."""
 
     resource = resources.webhook
@@ -419,8 +419,8 @@ class ResourceListTests(ExtraDataListMixin, BaseWebAPITestCase):
         self.compare_item(rsp['webhook'], WebHookTarget.objects.get())
 
 
-@six.add_metaclass(BasicTestsMetaclass)
-class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase):
+class ResourceItemTests(ExtraDataItemMixin, BaseWebAPITestCase,
+                        metaclass=BasicTestsMetaclass):
     """Tests for the WebHookResource item resource."""
 
     resource = resources.webhook
