diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py
index cf6be0955fd9a7acea6a57e5d5bec63e4b6257ce..baebc10a429e9eca990150dfdc9fd2dda8bb2c21 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py
@@ -1,4 +1,3 @@
-# encoding: utf-8
 """
 Modulestore configuration for test cases.
 """
@@ -9,14 +8,13 @@ import functools
 import os
 from contextlib import contextmanager
 from enum import Enum
+from unittest.mock import patch
 
 from django.conf import settings
 from django.contrib.auth.models import AnonymousUser, User  # lint-amnesty, pylint: disable=imported-auth-user
 from django.db import connections
 from django.test import TestCase
 from django.test.utils import override_settings
-from mock import patch
-from six.moves import range
 
 from lms.djangoapps.courseware.tests.factories import StaffFactory
 from lms.djangoapps.courseware.field_overrides import OverrideFieldData
@@ -43,7 +41,7 @@ class CourseUserType(Enum):
     UNENROLLED_STAFF = 'unenrolled_staff'
 
 
-class StoreConstructors(object):
+class StoreConstructors:
     """Enumeration of store constructor types."""
     draft, split = list(range(2))
 
@@ -108,7 +106,7 @@ def draft_mongo_store_config(data_dir):
             'DOC_STORE_CONFIG': {
                 'host': MONGO_HOST,
                 'port': MONGO_PORT_NUM,
-                'db': 'test_xmodule_{}'.format(os.getpid()),
+                'db': f'test_xmodule_{os.getpid()}',
                 'collection': 'modulestore',
             },
             'OPTIONS': modulestore_options
@@ -135,7 +133,7 @@ def split_mongo_store_config(data_dir):
             'DOC_STORE_CONFIG': {
                 'host': MONGO_HOST,
                 'port': MONGO_PORT_NUM,
-                'db': 'test_xmodule_{}'.format(os.getpid()),
+                'db': f'test_xmodule_{os.getpid()}',
                 'collection': 'modulestore',
             },
             'OPTIONS': modulestore_options
@@ -154,7 +152,7 @@ def contentstore_config():
         'ENGINE': 'xmodule.contentstore.mongo.MongoContentStore',
         'DOC_STORE_CONFIG': {
             'host': MONGO_HOST,
-            'db': 'test_xcontent_{}'.format(os.getpid()),
+            'db': f'test_xcontent_{os.getpid()}',
             'port': MONGO_PORT_NUM,
         },
         # allow for additional options that can be keyed on a name, e.g. 'trashcan'
@@ -210,7 +208,7 @@ TEST_DATA_SPLIT_MODULESTORE = functools.partial(
 )
 
 
-class SignalIsolationMixin(object):
+class SignalIsolationMixin:
     """
     Simple utility mixin class to toggle ModuleStore signals on and off. This
     class operates on `SwitchedSignal` objects on the modulestore's
@@ -421,7 +419,7 @@ class SharedModuleStoreTestCase(
         # Now yield to allow the test class to run its setUpClass() setup code.
         yield
         # Now call the base class, which calls back into the test class's setUpTestData().
-        super(SharedModuleStoreTestCase, cls).setUpClass()
+        super().setUpClass()
 
     @classmethod
     def setUpClass(cls):
@@ -429,19 +427,19 @@ class SharedModuleStoreTestCase(
         Start modulestore isolation, and then load modulestore specific
         test data.
         """
-        super(SharedModuleStoreTestCase, cls).setUpClass()
+        super().setUpClass()
         cls.start_modulestore_isolation()
 
     @classmethod
     def tearDownClass(cls):
         cls.end_modulestore_isolation()
-        super(SharedModuleStoreTestCase, cls).tearDownClass()
+        super().tearDownClass()
 
     def setUp(self):
         # OverrideFieldData.provider_classes is always reset to `None` so
         # that they're recalculated for every test
         OverrideFieldData.provider_classes = None
-        super(SharedModuleStoreTestCase, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
 
 class ModuleStoreTestCase(
@@ -491,11 +489,11 @@ class ModuleStoreTestCase(
 
     @classmethod
     def setUpClass(cls):
-        super(ModuleStoreTestCase, cls).setUpClass()
+        super().setUpClass()
 
     @classmethod
     def tearDownClass(cls):
-        super(ModuleStoreTestCase, cls).tearDownClass()
+        super().tearDownClass()
 
     def setUp(self):
         """
@@ -511,7 +509,7 @@ class ModuleStoreTestCase(
         # that they're recalculated for every test
         OverrideFieldData.provider_classes = None
 
-        super(ModuleStoreTestCase, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
         self.store = modulestore()
 
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/factories.py b/common/lib/xmodule/xmodule/modulestore/tests/factories.py
index 37675dd84f9c6631b085e396593eedaf3e013334..7717581dd9bd9a37392a04289796943862cbb756 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/factories.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/factories.py
@@ -11,13 +11,12 @@ import traceback
 from collections import defaultdict
 from contextlib import contextmanager
 from uuid import uuid4
-import pytz
+from unittest.mock import patch
 
 import pymongo.message
-import six
+import pytz
 from factory import Factory, Sequence, lazy_attribute, lazy_attribute_sequence
 from factory.errors import CyclicDefinitionError
-from mock import patch
 from opaque_keys.edx.keys import UsageKey
 from opaque_keys.edx.locator import BlockUsageLocator
 from xblock.core import XBlock
@@ -31,7 +30,7 @@ from xmodule.tabs import CourseTab
 LOG = logging.getLogger(__name__)
 
 
-class Dummy(object):
+class Dummy:
     pass
 
 
@@ -45,7 +44,7 @@ class XModuleFactoryLock(threading.local):
     will be called.
     """
     def __init__(self):
-        super(XModuleFactoryLock, self).__init__()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__()
         self._enabled = False
 
     def enable(self):
@@ -81,7 +80,7 @@ class XModuleFactory(Factory):
     # We have to give a model for Factory.
     # However, the class that we create is actually determined by the category
     # specified in the factory
-    class Meta(object):
+    class Meta:
         model = Dummy
 
     @lazy_attribute
@@ -155,7 +154,7 @@ class SampleCourseFactory(CourseFactory):
         user_id = kwargs.get('user_id', ModuleStoreEnum.UserID.test)
 
         with store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, None):
-            course = super(SampleCourseFactory, cls)._create(target_class, **kwargs)
+            course = super()._create(target_class, **kwargs)
 
             def create_sub_tree(parent_loc, block_info):
                 """Recursively creates a sub_tree on this parent_loc with this block."""
@@ -216,7 +215,7 @@ class ToyCourseFactory(SampleCourseFactory):
         }
         fields.update(kwargs)
 
-        toy_course = super(ToyCourseFactory, cls)._create(
+        toy_course = super()._create(
             target_class,
             **fields
         )
@@ -292,9 +291,9 @@ class ItemFactory(XModuleFactory):
     @lazy_attribute_sequence
     def display_name(self, n):  # lint-amnesty, pylint: disable=missing-function-docstring
         if self.descriptive_tag:
-            return "{} {} - {}".format(self.category, n, self.descriptive_tag)
+            return f"{self.category} {n} - {self.descriptive_tag}"
         else:
-            return "{} {}".format(self.category, n)
+            return f"{self.category} {n}"
 
     @lazy_attribute
     def location(self):  # lint-amnesty, pylint: disable=missing-function-docstring
@@ -389,7 +388,7 @@ class ItemFactory(XModuleFactory):
                 template = clz.get_template(template_id)
                 assert template is not None
                 metadata.update(template.get('metadata', {}))
-                if not isinstance(data, six.string_types):
+                if not isinstance(data, str):
                     data.update(template.get('data'))
 
             # replace the display name with an optional parameter passed in from the caller
@@ -464,7 +463,7 @@ def check_number_of_calls(object_with_method, method_name, maximum_calls, minimu
     )
 
 
-class StackTraceCounter(object):
+class StackTraceCounter:
     """
     A class that counts unique stack traces underneath a particular stack frame.
     """
@@ -505,13 +504,13 @@ class StackTraceCounter(object):
                 try:
                     safe_args.append(repr(arg))
                 except Exception as exc:
-                    safe_args.append('<un-repr-able value: {}'.format(exc))
+                    safe_args.append(f'<un-repr-able value: {exc}')
             safe_kwargs = {}
             for key, kwarg in kwargs.items():
                 try:
                     safe_kwargs[key] = repr(kwarg)
                 except Exception as exc:
-                    safe_kwargs[key] = '<un-repr-able value: {}'.format(exc)
+                    safe_kwargs[key] = f'<un-repr-able value: {exc}'
 
             self._stacks[tuple(stack)][tuple(safe_args), tuple(safe_kwargs.items())] += 1
         else:
@@ -612,8 +611,8 @@ def check_sum_of_calls(object_, methods, maximum_calls, minimum_calls=1, include
                 messages.append("\n\n")
                 if include_arguments:
                     for (args, kwargs), count in stack_counter[stack].items():
-                        messages.append("      called {} times with:\n".format(count))
-                        messages.append("      args: {}\n".format(args))
+                        messages.append(f"      called {count} times with:\n")
+                        messages.append(f"      args: {args}\n")
                         messages.append("      kwargs: {}\n\n".format(dict(kwargs)))
 
     # verify that we called the methods within the desired range
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/sample_courses.py b/common/lib/xmodule/xmodule/modulestore/tests/sample_courses.py
index f2fb7ab50632b5ddc318092dec0abbee6feb96e5..a94f7834a99da9954c5e99475cabb57efa8cbadd 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/sample_courses.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/sample_courses.py
@@ -1,4 +1,3 @@
-# encoding: utf-8
 """
 The data type and use of it for declaratively creating test courses.
 """
@@ -67,7 +66,7 @@ TOY_BLOCK_INFO_TREE = [
                     ),
                     BlockInfo(
                         "toyjumpto", "html", {
-                            "data": u"<a href=\"/jump_to_id/vertical_test\">This is a link to another page and some Chinese 四節比分和七年前</a> <p>Some more Chinese 四節比分和七年前</p>\n",  # lint-amnesty, pylint: disable=line-too-long
+                            "data": "<a href=\"/jump_to_id/vertical_test\">This is a link to another page and some Chinese 四節比分和七年前</a> <p>Some more Chinese 四節比分和七年前</p>\n",  # lint-amnesty, pylint: disable=line-too-long
                             "xml_attributes": {"filename": ["html/toyjumpto.xml", "html/toyjumpto.xml"]}
                         }, []),
                     BlockInfo(
@@ -129,7 +128,7 @@ TOY_BLOCK_INFO_TREE = [
         "poll_test", "chapter", {}, [
             BlockInfo(
                 "T1_changemind_poll_foo", "poll_question", {
-                    "question": u"<p>Have you changed your mind? ’</p>",
+                    "question": "<p>Have you changed your mind? ’</p>",
                     "answers": [{"text": "Yes", "id": "yes"}, {"text": "No", "id": "no"}],
                     "xml_attributes": {"reset": "false", "filename": ["", None]},
                     "display_name": "Change your answer"
@@ -177,7 +176,7 @@ TOY_BLOCK_INFO_TREE = [
                         }, []),
                 ]),
                 BlockInfo("unicode", "html", {
-                    "data": u"…", "xml_attributes": {"filename": ["", None]}
+                    "data": "…", "xml_attributes": {"filename": ["", None]}
                 }, [])
             ]),
         ]
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_asides.py b/common/lib/xmodule/xmodule/modulestore/tests/test_asides.py
index e336621c2e928f4f2af9410ea2a435dd22ed613d..052fc6637e61c8e28598cfac0be7de12c9d38c99 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_asides.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_asides.py
@@ -4,8 +4,8 @@ Tests for Asides
 
 
 from unittest import TestCase
+from unittest.mock import patch
 
-from mock import patch
 from web_fragments.fragment import Fragment
 from xblock.core import XBlockAside
 from xblock.fields import Scope, String
@@ -17,7 +17,7 @@ class AsideTestType(XBlockAside):
     """
     Test Aside type
     """
-    FRAG_CONTENT = u"<p>Aside rendered</p>"
+    FRAG_CONTENT = "<p>Aside rendered</p>"
 
     content = String(default="default_content", scope=Scope.content)
     data_field = String(default="default_data", scope=Scope.settings)
@@ -45,11 +45,11 @@ class TestAsidesXmlStore(TestCase):
                 Check whether block has the expected aside w/ its fields and then recurse to the block's children
                 """
                 asides = block.runtime.get_asides(block)
-                assert len(asides) == 1, 'Found {} asides but expected only test_aside'.format(asides)
+                assert len(asides) == 1, f'Found {asides} asides but expected only test_aside'
                 assert isinstance(asides[0], AsideTestType)
                 category = block.scope_ids.block_type
-                assert asides[0].data_field == '{} aside data'.format(category)
-                assert asides[0].content == '{} Aside'.format(category.capitalize())
+                assert asides[0].data_field == f'{category} aside data'
+                assert asides[0].content == f'{category.capitalize()} Aside'
 
                 for child in block.get_children():
                     check_block(child)
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py
index 24ff7f5569a75806702c0edfebf56a3f34a32655..04521b5d605825a55a93e29179d24c2ce42331fd 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py
@@ -9,12 +9,10 @@ from datetime import datetime, timedelta
 import pytest
 import ddt
 import pytz
-import six
 
 from django.test import TestCase
 from opaque_keys.edx.keys import CourseKey
 from opaque_keys.edx.locator import CourseLocator
-from six.moves import range, zip
 
 from openedx.core.lib.tests import attr
 from xmodule.assetstore import AssetMetadata
@@ -29,16 +27,13 @@ from xmodule.modulestore.tests.utils import (
 )
 
 
-class AssetStoreTestData(object):
+class AssetStoreTestData:
     """
     Shared data for constructing test assets.
     """
     now = datetime.now(pytz.utc)
     user_id = 144
-    if six.PY2:
-        user_id_long = long(user_id)  # lint-amnesty, pylint: disable=undefined-variable
-    else:
-        user_id_long = int(user_id)
+    user_id_long = int(user_id)
 
     user_email = "me@example.com"
 
@@ -75,7 +70,7 @@ class TestSortedAssetList(unittest.TestCase):
     """
 
     def setUp(self):
-        super(TestSortedAssetList, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         asset_list = [dict(list(zip(AssetStoreTestData.asset_fields, asset))) for asset in AssetStoreTestData.all_asset_data]  # lint-amnesty, pylint: disable=line-too-long
         self.sorted_asset_list_by_filename = SortedAssetList(iterable=asset_list)
         self.sorted_asset_list_by_last_edit = SortedAssetList(iterable=asset_list, key=lambda x: x['edited_on'])
@@ -105,7 +100,7 @@ class TestMongoAssetMetadataStorage(TestCase):
     }
 
     def setUp(self):
-        super(TestMongoAssetMetadataStorage, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
         self.differents = (('different', 'burn.jpg'),)
         self.vrmls = (
@@ -560,7 +555,7 @@ class TestMongoAssetMetadataStorage(TestCase):
                 course1.id, None, start=0, maxresults=-1,
                 sort=('displayname', ModuleStoreEnum.SortOrder.ascending)
             )
-            assert len(assets) == len((self.differents + self.vrmls))
+            assert len(assets) == len(self.differents + self.vrmls)
             self._check_asset_values(assets, self.differents + self.vrmls)
 
     @ddt.data(*MODULESTORE_SETUPS)
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_contentstore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_contentstore.py
index 3b78556bd8e5da31e6ce358b3d9d21b5d33aeaa5..b167bc221df59fdd59a3db151ed708122487467a 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_contentstore.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_contentstore.py
@@ -52,7 +52,7 @@ class TestContentstore(unittest.TestCase):
             CourseLocator.deprecated = cls.ssck_deprecated
         else:
             del CourseLocator.deprecated
-        return super(TestContentstore, cls).tearDownClass()
+        return super().tearDownClass()
 
     def set_up_assets(self, deprecated):
         """
@@ -86,7 +86,7 @@ class TestContentstore(unittest.TestCase):
         """
         Load and save the given file.
         """
-        with open("{}/static/{}".format(DATA_DIR, filename), "rb") as f:
+        with open(f"{DATA_DIR}/static/{filename}", "rb") as f:
             content = StaticContent(
                 asset_key, displayname, mimetypes.guess_type(filename)[0], f.read(),
                 locked=locked
@@ -115,9 +115,9 @@ class TestContentstore(unittest.TestCase):
         """
         self.set_up_assets(deprecated)
         asset_key = self.course1_key.make_asset_key('asset', self.course1_files[0])
-        assert self.contentstore.find(asset_key) is not None, 'Could not find {}'.format(asset_key)
+        assert self.contentstore.find(asset_key) is not None, f'Could not find {asset_key}'
 
-        assert self.contentstore.find(asset_key, as_stream=True) is not None, 'Could not find {}'.format(asset_key)
+        assert self.contentstore.find(asset_key, as_stream=True) is not None, f'Could not find {asset_key}'
 
         unknown_asset = self.course1_key.make_asset_key('asset', 'no_such_file.gif')
         with pytest.raises(NotFoundError):
@@ -139,11 +139,11 @@ class TestContentstore(unittest.TestCase):
             )
             for filename in self.course1_files:
                 filepath = path.Path(root_dir / filename)
-                assert filepath.isfile(), '{} is not a file'.format(filepath)
+                assert filepath.isfile(), f'{filepath} is not a file'
             for filename in self.course2_files:
                 if filename not in self.course1_files:
                     filepath = path.Path(root_dir / filename)
-                    assert not filepath.isfile(), '{} is unexpected exported a file'.format(filepath)
+                    assert not filepath.isfile(), f'{filepath} is unexpected exported a file'
         finally:
             shutil.rmtree(root_dir)
 
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py b/common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py
index f44516b02db7bf7fddf85476c6ace29f6831a4f2..49f607e43963d6566155a4e3d600aec01b0ef5bf 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py
@@ -17,9 +17,9 @@ import itertools
 import os
 from shutil import rmtree
 from tempfile import mkdtemp
+from unittest.mock import patch
 
 import ddt
-from mock import patch
 from path import Path as path
 
 from openedx.core.lib.tests import attr
@@ -43,7 +43,7 @@ COURSE_DATA_NAMES = (
     'split_test_module_draft',
 )
 
-EXPORTED_COURSE_DIR_NAME = u'exported_source_course'
+EXPORTED_COURSE_DIR_NAME = 'exported_source_course'
 
 
 @ddt.ddt
@@ -55,7 +55,7 @@ class CrossStoreXMLRoundtrip(CourseComparisonTest, PartitionTestCase):
     """
 
     def setUp(self):
-        super(CrossStoreXMLRoundtrip, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.export_dir = mkdtemp()
         self.addCleanup(rmtree, self.export_dir, ignore_errors=True)
 
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_inheritance.py b/common/lib/xmodule/xmodule/modulestore/tests/test_inheritance.py
index 3a1e27972c2e188068458e0d202d058dcb2a1768..eb98cbc4f9f9116c1e5d2a32efd4c9c97ec81307 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_inheritance.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_inheritance.py
@@ -4,10 +4,10 @@ Unit tests for testing inheritance mixins
 
 
 import unittest
+from unittest.mock import Mock
 
 import ddt
 from django.utils.timezone import now, timedelta
-from mock import Mock
 from xblock.core import XBlock
 from xblock.fields import ScopeIds
 from xblock.test.tools import TestRuntime
@@ -38,7 +38,7 @@ class TestInheritanceMixin(unittest.TestCase):
         self.xblock = runtime.construct_xblock_from_class(
             TestXBlock, ScopeIds('user', 'TestXBlock', 'def_id', 'usage_id')
         )
-        super(TestInheritanceMixin, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
     def add_submission_deadline_information(self, due_date, graceperiod, self_paced):
         """
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_libraries.py b/common/lib/xmodule/xmodule/modulestore/tests/test_libraries.py
index 0ea137fc94ed9bd7f24532543c7e35abb5e09841..6cb17268a740faa6b9ae95e4fd8fc47ae9ea0171 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_libraries.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_libraries.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 """
 Basic unit tests related to content libraries.
 
@@ -7,10 +6,8 @@ Higher-level tests are in `cms/djangoapps/contentstore`.
 
 import pytest
 import ddt
-import six
 from bson.objectid import ObjectId
 from opaque_keys.edx.locator import LibraryLocator
-from six.moves import range
 
 from xmodule.modulestore.exceptions import DuplicateCourseError
 from xmodule.modulestore.tests.factories import ItemFactory, LibraryFactory, check_mongo_calls
@@ -50,15 +47,15 @@ class TestLibraries(MixedSplitTestCase):
 
     @ddt.data(
         "This is a test library!",
-        u"Ωμέγα Βιβλιοθήκη",
+        "Ωμέγα Βιβλιοθήκη",
     )
     def test_str_repr(self, name):
         """
         Test __unicode__() and __str__() methods of libraries
         """
         library = LibraryFactory.create(metadata={"display_name": name}, modulestore=self.store)
-        assert name in six.text_type(library)
-        if not isinstance(name, six.text_type):
+        assert name in str(library)
+        if not isinstance(name, str):
             assert name in str(library)
 
     def test_display_with_default_methods(self):
@@ -155,7 +152,7 @@ class TestLibraries(MixedSplitTestCase):
     def test_get_libraries(self):
         """ Test get_libraries() """
         libraries = [LibraryFactory.create(modulestore=self.store) for _ in range(3)]
-        lib_dict = dict([(lib.location.library_key, lib) for lib in libraries])  # lint-amnesty, pylint: disable=consider-using-dict-comprehension
+        lib_dict = {lib.location.library_key: lib for lib in libraries}
 
         lib_list = self.store.get_libraries()
 
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
index d03fdfa2f49b14c517829253f548e692f5a391ba..b983a6b79f4d8e6aa8f763fd943351643c04c13f 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
@@ -12,20 +12,18 @@ from contextlib import contextmanager
 from shutil import rmtree
 from tempfile import mkdtemp
 from uuid import uuid4
+from unittest.mock import Mock, call, patch
 
 import ddt
 import pymongo
 import pytest
-import six
 # Mixed modulestore depends on django, so we'll manually configure some django settings
 # before importing the module
 # TODO remove this import and the configuration -- xmodule should not depend on django!
 from django.conf import settings
-from mock import Mock, call, patch
 from opaque_keys.edx.keys import CourseKey
 from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator, LibraryLocator
 from pytz import UTC
-from six.moves import range
 from web_fragments.fragment import Fragment
 from xblock.core import XBlockAside
 from xblock.fields import Scope, ScopeIds, String
@@ -121,7 +119,7 @@ class CommonMixedModuleStoreSetup(CourseComparisonTest):
         """
         Set up the database for testing
         """
-        super(CommonMixedModuleStoreSetup, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
         self.exclude_field(None, 'wiki_slug')
         self.exclude_field(None, 'xml_attributes')
@@ -281,7 +279,7 @@ class AsideFoo(XBlockAside):
     """
     Test xblock aside class
     """
-    FRAG_CONTENT = u"<p>Aside Foo rendered</p>"
+    FRAG_CONTENT = "<p>Aside Foo rendered</p>"
 
     field11 = String(default="aside1_default_value1", scope=Scope.content)
     field12 = String(default="aside1_default_value2", scope=Scope.settings)
@@ -296,7 +294,7 @@ class AsideBar(XBlockAside):
     """
     Test xblock aside class
     """
-    FRAG_CONTENT = u"<p>Aside Bar rendered</p>"
+    FRAG_CONTENT = "<p>Aside Bar rendered</p>"
 
     field21 = String(default="aside2_default_value1", scope=Scope.content)
     field22 = String(default="aside2_default_value2", scope=Scope.settings)
@@ -483,7 +481,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
 
         items = self.store.get_items(course_key)
         # Check items found are either course or about type
-        assert set(['course', 'about']).issubset(set([item.location.block_type for item in items]))  # pylint: disable=consider-using-set-comprehension, line-too-long
+        assert {'course', 'about'}.issubset({item.location.block_type for item in items})  # pylint: disable=line-too-long
         # Assert that about is a detached category found in get_items
         assert [item.location.block_type for item in items if item.location.block_type == 'about'][0]\
                in DETACHED_XBLOCK_TYPES
@@ -511,7 +509,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
         items_in_tree = self.store.get_items(course_key, include_orphans=False)
 
         # Check that course and about blocks are found in get_items
-        assert set(['course', 'about']).issubset({item.location.block_type for item in items_in_tree})
+        assert {'course', 'about'}.issubset({item.location.block_type for item in items_in_tree})
         # Check orphan is found or not - this is based on mongo/split modulestore. It should be found in mongo.
         assert (orphan in [item.location for item in items_in_tree]) == orphan_in_items
         assert len(items_in_tree) == expected_items_in_tree
@@ -1046,7 +1044,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
         with check_mongo_calls(max_find, max_send):
             courses = self.store.get_courses()
             course_ids = [course.location for course in courses]
-            assert len(courses) == 1, 'Not one course: {}'.format(course_ids)
+            assert len(courses) == 1, f'Not one course: {course_ids}'
             assert self.course_locations[self.MONGO_COURSEID] in course_ids
 
         with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred):
@@ -1608,7 +1606,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
         # add another parent (unit) "vertical_x1b" for problem "problem_x1a_1"
         mongo_store.collection.update_one(
             self.vertical_x1b.to_deprecated_son('_id.'),  # lint-amnesty, pylint: disable=no-member
-            {'$push': {'definition.children': six.text_type(self.problem_x1a_1)}}  # lint-amnesty, pylint: disable=no-member
+            {'$push': {'definition.children': str(self.problem_x1a_1)}}  # lint-amnesty, pylint: disable=no-member
         )
 
         # convert first parent (unit) "vertical_x1a" of problem "problem_x1a_1" to draft
@@ -1647,7 +1645,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
 
             should_work = (
                 (self.problem_x1a_2,  # lint-amnesty, pylint: disable=no-member
-                 (course_key, u"Chapter_x", u"Sequential_x1", u'Vertical_x1a', '1', self.problem_x1a_2)),  # lint-amnesty, pylint: disable=no-member
+                 (course_key, "Chapter_x", "Sequential_x1", 'Vertical_x1a', '1', self.problem_x1a_2)),  # lint-amnesty, pylint: disable=no-member
                 (self.chapter_x,  # lint-amnesty, pylint: disable=no-member
                  (course_key, "Chapter_x", None, None, None, self.chapter_x)),  # lint-amnesty, pylint: disable=no-member
             )
@@ -1908,7 +1906,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
 
         with check_mongo_calls(max_find, max_send):
             found_orphans = self.store.get_orphans(self.course_locations[self.MONGO_COURSEID].course_key)
-        six.assertCountEqual(self, found_orphans, orphan_locations)
+        self.assertCountEqual(found_orphans, orphan_locations)
 
     @ddt.data(ModuleStoreEnum.Type.mongo)
     def test_get_non_orphan_parents(self, default_ms):
@@ -1948,11 +1946,11 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
         # add orphan vertical and sequential as another parents of problem "problem_x1a_1"
         mongo_store.collection.update_one(
             orphan_sequential.to_deprecated_son('_id.'),
-            {'$push': {'definition.children': six.text_type(self.problem_x1a_1)}}  # lint-amnesty, pylint: disable=no-member
+            {'$push': {'definition.children': str(self.problem_x1a_1)}}  # lint-amnesty, pylint: disable=no-member
         )
         mongo_store.collection.update_one(
             orphan_vertical.to_deprecated_son('_id.'),
-            {'$push': {'definition.children': six.text_type(self.problem_x1a_1)}}  # lint-amnesty, pylint: disable=no-member
+            {'$push': {'definition.children': str(self.problem_x1a_1)}}  # lint-amnesty, pylint: disable=no-member
         )
         # test that "get_parent_location" method of published branch still returns the correct non-orphan parent for
         # problem "problem_x1a_1" since the two other parents are orphans
@@ -1961,7 +1959,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
             assert parent == self.vertical_x1a  # lint-amnesty, pylint: disable=no-member
 
         # now add valid published vertical as another parent of problem
-        mongo_store.collection.update_one(self.sequential_x1.to_deprecated_son('_id.'), {'$push': {'definition.children': six.text_type(self.problem_x1a_1)}})  # lint-amnesty, pylint: disable=no-member, line-too-long
+        mongo_store.collection.update_one(self.sequential_x1.to_deprecated_son('_id.'), {'$push': {'definition.children': str(self.problem_x1a_1)}})  # lint-amnesty, pylint: disable=no-member, line-too-long
         # now check that "get_parent_location" method of published branch raises "ReferentialIntegrityError" for
         # problem "problem_x1a_1" since it has now 2 valid published parents
         with self.store.branch_setting(ModuleStoreEnum.Branch.published_only, course_id):
@@ -1983,7 +1981,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
             block_id='orphan'
         )
         orphans = self.store.get_orphans(self.course_locations[self.MONGO_COURSEID].course_key)
-        assert len(orphans) == 0, 'unexpected orphans: {}'.format(orphans)
+        assert len(orphans) == 0, f'unexpected orphans: {orphans}'
 
     @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
     def test_create_item_populates_edited_info(self, default_ms):
@@ -2487,7 +2485,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
         self._initialize_mixed(mappings={})
 
         fake_store = "fake"
-        with self.assertRaisesRegex(Exception, "Cannot find store of type {}".format(fake_store)):
+        with self.assertRaisesRegex(Exception, f"Cannot find store of type {fake_store}"):
             with self.store.default_store(fake_store):
                 pass  # pragma: no cover
 
@@ -2495,7 +2493,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
         """
         Load and save the given file. (taken from test_contentstore)
         """
-        with open("{}/static/{}".format(DATA_DIR, asset_key.block_id), "rb") as f:
+        with open(f"{DATA_DIR}/static/{asset_key.block_id}", "rb") as f:
             content = StaticContent(
                 asset_key, "Funky Pix", mimetypes.guess_type(asset_key.block_id)[0], f.read(),
             )
@@ -3002,7 +3000,7 @@ class TestPublishOverExportImport(CommonMixedModuleStoreSetup):
         """
         Set up the database for testing
         """
-        super(TestPublishOverExportImport, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
         self.user_id = ModuleStoreEnum.UserID.test
         self.export_dir = mkdtemp()
@@ -3353,11 +3351,11 @@ class TestPublishOverExportImport(CommonMixedModuleStoreSetup):
                     """
                     asides = block.runtime.get_asides(block)
 
-                    assert len(asides) == 1, 'Found {} asides but expected only test_aside'.format(asides)
+                    assert len(asides) == 1, f'Found {asides} asides but expected only test_aside'
                     assert isinstance(asides[0], AsideTestType)
                     category = block.scope_ids.block_type
-                    assert asides[0].data_field == '{} aside data'.format(category)
-                    assert asides[0].content == '{} Aside'.format(category.capitalize())
+                    assert asides[0].data_field == f'{category} aside data'
+                    assert asides[0].content == f'{category.capitalize()} Aside'
 
                     for child in block.get_children():
                         check_block(child)
@@ -3368,7 +3366,7 @@ class TestPublishOverExportImport(CommonMixedModuleStoreSetup):
                 new_chapter = self.store.create_child(self.user_id, courses[0].location, 'chapter', 'new_chapter')
                 asides = new_chapter.runtime.get_asides(new_chapter)
 
-                assert len(asides) == 1, 'Found {} asides but expected only test_aside'.format(asides)
+                assert len(asides) == 1, f'Found {asides} asides but expected only test_aside'
                 chapter_aside = asides[0]
                 assert isinstance(chapter_aside, AsideTestType)
                 assert not chapter_aside.fields['data_field'].is_set_on(chapter_aside), \
@@ -3468,11 +3466,11 @@ class TestPublishOverExportImport(CommonMixedModuleStoreSetup):
                     """
                     asides = block.runtime.get_asides(block)
 
-                    assert len(asides) == 1, 'Found {} asides but expected only test_aside'.format(asides)
+                    assert len(asides) == 1, f'Found {asides} asides but expected only test_aside'
                     assert isinstance(asides[0], AsideTestType)
                     category = block.scope_ids.block_type
-                    assert asides[0].data_field == 'Exported data_field {} aside data'.format(category)
-                    assert asides[0].content == 'Exported content {} Aside'.format(category.capitalize())
+                    assert asides[0].data_field == f'Exported data_field {category} aside data'
+                    assert asides[0].content == f'Exported content {category.capitalize()} Aside'
 
                     for child in block.get_children():
                         check_block(child)
@@ -3515,7 +3513,7 @@ class TestPublishOverExportImport(CommonMixedModuleStoreSetup):
                 new_chapter.display_name = new_chapter_display_name
                 asides = new_chapter.runtime.get_asides(new_chapter)
 
-                assert len(asides) == 1, 'Found {} asides but expected only test_aside'.format(asides)
+                assert len(asides) == 1, f'Found {asides} asides but expected only test_aside'
                 chapter_aside = asides[0]
                 assert isinstance(chapter_aside, AsideTestType)
                 chapter_aside.data_field = 'new value'
@@ -3528,7 +3526,7 @@ class TestPublishOverExportImport(CommonMixedModuleStoreSetup):
                 new_problem.display_name = new_problem_display_name
                 asides = new_problem.runtime.get_asides(new_problem)
 
-                assert len(asides) == 1, 'Found {} asides but expected only test_aside'.format(asides)
+                assert len(asides) == 1, f'Found {asides} asides but expected only test_aside'
                 problem_aside = asides[0]
                 assert isinstance(problem_aside, AsideTestType)
                 problem_aside.data_field = 'new problem value'
@@ -3607,7 +3605,7 @@ class TestAsidesWithMixedModuleStore(CommonMixedModuleStoreSetup):
         """
         Setup environment for testing
         """
-        super(TestAsidesWithMixedModuleStore, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         key_store = DictKeyValueStore()
         field_data = KvsFieldData(key_store)
         self.runtime = TestRuntime(services={'field-data': field_data})
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_modulestore_settings.py b/common/lib/xmodule/xmodule/modulestore/tests/test_modulestore_settings.py
index 349c93b474c2105728a27cce26ad959d0b101c42..db267b942fb262402e26c23e04492be85c040198 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_modulestore_settings.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_modulestore_settings.py
@@ -5,6 +5,7 @@ Tests for testing the modulestore settings migration code.
 
 import copy
 from unittest import TestCase
+
 import pytest
 import ddt
 
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
index 7a9d88ba1bfc5eb960b70f5bcca3348f6c1b79de..4d81e6081e091aa5cddaea40c318a10d324f3acb 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
@@ -7,16 +7,15 @@ import logging
 import shutil
 from datetime import datetime
 from tempfile import mkdtemp
+from unittest.mock import patch
 from uuid import uuid4
 
 import pymongo
 import pytest
-import six
 
 # pylint: disable=protected-access
 from django.test import TestCase
 # pylint: enable=E0611
-from mock import patch
 from opaque_keys.edx.keys import CourseKey, UsageKey
 from opaque_keys.edx.locator import AssetLocator, BlockUsageLocator, CourseLocator, LibraryLocator
 from path import Path as path
@@ -172,7 +171,7 @@ class TestMongoModuleStoreBase(TestCase):
         connection.drop_database(DB)
 
     def setUp(self):
-        super(TestMongoModuleStoreBase, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.dummy_user = ModuleStoreEnum.UserID.test
 
 
@@ -188,11 +187,11 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
 
     @classmethod
     def setUpClass(cls):
-        super(TestMongoModuleStore, cls).setUpClass()
+        super().setUpClass()
 
     @classmethod
     def tearDownClass(cls):
-        super(TestMongoModuleStore, cls).tearDownClass()
+        super().tearDownClass()
 
     def test_init(self):
         '''Make sure the db loads'''
@@ -370,7 +369,7 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
         courses = self.draft_store.get_courses()
         for course in courses:
             assert not ((course.location.org == 'edx') and (course.location.course == 'templates')),\
-                '{0} is a template course'.format(course)
+                f'{course} is a template course'
 
     def test_contentstore_attrs(self):
         """
@@ -523,7 +522,7 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
             for ref in refele.reference_list:
                 assert isinstance(ref, UsageKey)
             assert len(refele.reference_dict) > 0
-            for ref in six.itervalues(refele.reference_dict):
+            for ref in refele.reference_dict.values():
                 assert isinstance(ref, UsageKey)
 
         def check_mongo_fields():
@@ -532,17 +531,17 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
 
             def check_children(payload):
                 for child in payload['definition']['children']:
-                    assert isinstance(child, six.string_types)
+                    assert isinstance(child, str)
 
             refele = get_item(self.refloc)
             check_children(refele)
-            assert isinstance(refele['definition']['data']['reference_link'], six.string_types)
+            assert isinstance(refele['definition']['data']['reference_link'], str)
             assert len(refele['definition']['data']['reference_list']) > 0
             for ref in refele['definition']['data']['reference_list']:
-                assert isinstance(ref, six.string_types)
+                assert isinstance(ref, str)
             assert len(refele['metadata']['reference_dict']) > 0
-            for ref in six.itervalues(refele['metadata']['reference_dict']):
-                assert isinstance(ref, six.string_types)
+            for ref in refele['metadata']['reference_dict'].values():
+                assert isinstance(ref, str)
 
         setup_test()
         check_xblock_fields()
@@ -563,9 +562,9 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
 
         root_dir = path(mkdtemp())
         self.addCleanup(shutil.rmtree, root_dir)
-        export_course_to_xml(self.draft_store, self.content_store, course_key, root_dir, u'test_export')
-        assert path((root_dir / 'test_export/static/images/course_image.jpg')).isfile()
-        assert path((root_dir / 'test_export/static/images_course_image.jpg')).isfile()
+        export_course_to_xml(self.draft_store, self.content_store, course_key, root_dir, 'test_export')
+        assert path(root_dir / 'test_export/static/images/course_image.jpg').isfile()
+        assert path(root_dir / 'test_export/static/images_course_image.jpg').isfile()
 
     @patch('xmodule.video_module.video_module.edxval_api', None)
     @patch('xmodule.tabs.CourseTab.from_json', side_effect=mock_tab_from_json)
@@ -579,9 +578,9 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
 
         root_dir = path(mkdtemp())
         self.addCleanup(shutil.rmtree, root_dir)
-        export_course_to_xml(self.draft_store, self.content_store, course.id, root_dir, u'test_export')
-        assert path((root_dir / 'test_export/static/just_a_test.jpg')).isfile()
-        assert not path((root_dir / 'test_export/static/images/course_image.jpg')).isfile()
+        export_course_to_xml(self.draft_store, self.content_store, course.id, root_dir, 'test_export')
+        assert path(root_dir / 'test_export/static/just_a_test.jpg').isfile()
+        assert not path(root_dir / 'test_export/static/images/course_image.jpg').isfile()
 
     @patch('xmodule.video_module.video_module.edxval_api', None)
     def test_course_without_image(self):
@@ -592,9 +591,9 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
         course = self.draft_store.get_course(CourseKey.from_string('edX/simple_with_draft/2012_Fall'))
         root_dir = path(mkdtemp())
         self.addCleanup(shutil.rmtree, root_dir)
-        export_course_to_xml(self.draft_store, self.content_store, course.id, root_dir, u'test_export')
-        assert not path((root_dir / 'test_export/static/images/course_image.jpg')).isfile()
-        assert not path((root_dir / 'test_export/static/images_course_image.jpg')).isfile()
+        export_course_to_xml(self.draft_store, self.content_store, course.id, root_dir, 'test_export')
+        assert not path(root_dir / 'test_export/static/images/course_image.jpg').isfile()
+        assert not path(root_dir / 'test_export/static/images_course_image.jpg').isfile()
 
     def _create_test_tree(self, name, user_id=None):
         """
@@ -610,7 +609,7 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
             user_id = self.dummy_user
 
         org = 'edX'
-        course = 'tree{}'.format(name)
+        course = f'tree{name}'
         run = name
 
         if not self.draft_store.has_course(CourseKey.from_string('/'.join[org, course, run])):  # lint-amnesty, pylint: disable=unsubscriptable-object
@@ -701,8 +700,8 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
 
         # First child should have been moved to second position, and better child takes the lead
         course = self.draft_store.get_course(course.id)
-        assert six.text_type(course.children[1]) == six.text_type(first_child.location)
-        assert six.text_type(course.children[0]) == six.text_type(second_child.location)
+        assert str(course.children[1]) == str(first_child.location)
+        assert str(course.children[0]) == str(second_child.location)
 
         # Clean up the data so we don't break other tests which apparently expect a particular state
         self.draft_store.delete_course(course.id, self.dummy_user)
@@ -729,11 +728,11 @@ class TestMongoModuleStoreWithNoAssetCollection(TestMongoModuleStore):  # lint-a
 
     @classmethod
     def setUpClass(cls):
-        super(TestMongoModuleStoreWithNoAssetCollection, cls).setUpClass()
+        super().setUpClass()
 
     @classmethod
     def tearDownClass(cls):
-        super(TestMongoModuleStoreWithNoAssetCollection, cls).tearDownClass()
+        super().tearDownClass()
 
     def test_no_asset_collection(self):
         courses = self.draft_store.get_courses()
@@ -753,7 +752,7 @@ class TestMongoKeyValueStore(TestCase):
     """
 
     def setUp(self):
-        super(TestMongoKeyValueStore, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.data = {'foo': 'foo_value'}
         self.course_id = CourseKey.from_string('org/course/run')
         self.parent = self.course_id.make_usage_key('parent', 'p')
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo_call_count.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo_call_count.py
index c939147a7f7f5551535d92deb0f0c2344472b049..57eb4ba4857afe7a2ca2d3f0bf921c881943dc76 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo_call_count.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo_call_count.py
@@ -9,7 +9,6 @@ from tempfile import mkdtemp
 from unittest import skip
 
 import ddt
-import six
 from django.test import TestCase  # lint-amnesty, pylint: disable=reimported
 
 from xmodule.modulestore.tests.factories import check_mongo_calls
@@ -35,7 +34,7 @@ class CountMongoCallsXMLRoundtrip(TestCase):
     """
 
     def setUp(self):
-        super(CountMongoCallsXMLRoundtrip, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.export_dir = mkdtemp()
         self.addCleanup(rmtree, self.export_dir, ignore_errors=True)
 
@@ -112,7 +111,7 @@ class CountMongoCallsCourseTraversal(TestCase):
         if access_all_block_fields:
             # Read the fields on each block in order to ensure each block and its definition is loaded.
             for xblock in all_blocks:
-                for __, field in six.iteritems(xblock.fields):
+                for __, field in xblock.fields.items():
                     if field.is_set_on(xblock):
                         __ = field.read_from(xblock)
 
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_publish.py b/common/lib/xmodule/xmodule/modulestore/tests/test_publish.py
index 5ab6ec70a6a0b6cfbe89940175155f032fbf731b..efcf5ef68ca6fcdd2bebf94cbf979e23d0c41d29 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_publish.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_publish.py
@@ -15,8 +15,6 @@ from tempfile import mkdtemp
 
 import pytest
 import ddt
-import six
-from six.moves import range
 
 from openedx.core.lib.tests import attr
 from xmodule.exceptions import InvalidVersionError
@@ -48,7 +46,7 @@ class TestPublish(SplitWMongoCourseBootstrapper):
         # create course: finds: 1 to verify uniqueness, 1 to find parents
         # sends: 1 to create course, 1 to create overview
         with check_mongo_calls(4, 2):
-            super(TestPublish, self)._create_course(split=False)  # 2 inserts (course and overview)  # lint-amnesty, pylint: disable=super-with-arguments
+            super()._create_course(split=False)  # 2 inserts (course and overview)
 
         # with bulk will delay all inheritance computations which won't be added into the mongo_calls
         with self.draft_mongo.bulk_operations(self.old_course_key):
@@ -183,7 +181,7 @@ class DraftPublishedOpTestCourseSetup(unittest.TestCase):
             """
             Given a block_type/num, return a block id.
             """
-            return '{}{:02d}'.format(block_type, num)
+            return f'{block_type}{num:02d}'
 
         def _make_course_db_entry(parent_type, parent_id, block_id, idx, child_block_type, child_block_id_base):
             """
@@ -276,7 +274,7 @@ class DraftPublishedOpTestCourseSetup(unittest.TestCase):
         # data needed to check the OLX.
         self.course_db = {}
 
-        super(DraftPublishedOpTestCourseSetup, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
 
 class OLXFormatChecker(unittest.TestCase):
@@ -306,7 +304,7 @@ class OLXFormatChecker(unittest.TestCase):
         self._ensure_exported()
 
         block_path = os.path.join(self.root_export_dir, self.export_dir)  # pylint: disable=no-member
-        assert os.path.isdir(block_path), '{} is not a dir.'.format(block_path)
+        assert os.path.isdir(block_path), f'{block_path} is not a dir.'
         return block_path
 
     def _get_block_type_path(self, course_export_dir, block_type, draft):
@@ -322,7 +320,7 @@ class OLXFormatChecker(unittest.TestCase):
         """
         Return the course export filename for a block.
         """
-        return '{}.xml'.format(block_id)
+        return f'{block_id}.xml'
 
     def _get_block_contents(self, block_subdir_path, block_id):
         """
@@ -333,8 +331,8 @@ class OLXFormatChecker(unittest.TestCase):
 
         block_file = self._get_block_filename(block_id)
         block_file_path = os.path.join(block_subdir_path, block_file)
-        assert os.path.isfile(block_file_path), '{} is not an existing file.'.format(block_file_path)
-        with open(block_file_path, "r") as file_handle:
+        assert os.path.isfile(block_file_path), f'{block_file_path} is not an existing file.'
+        with open(block_file_path) as file_handle:
             return file_handle.read()
 
     def assertElementTag(self, element, tag):
@@ -390,7 +388,7 @@ class OLXFormatChecker(unittest.TestCase):
         is_draft = kwargs.pop('draft', False)
         block_path = self._get_block_type_path(course_export_dir, block_type, is_draft)
         block_file_path = os.path.join(block_path, self._get_block_filename(block_id))
-        assert not os.path.exists(block_file_path), '{} exists but should not!'.format(block_file_path)
+        assert not os.path.exists(block_file_path), f'{block_file_path} exists but should not!'
 
     def assertParentReferences(self, element, course_key, parent_type, parent_id, index_in_children_list):
         """
@@ -406,7 +404,7 @@ class OLXFormatChecker(unittest.TestCase):
         parent_key = course_key.make_usage_key(parent_type, parent_id)
 
         self.assertElementAttrsSubset(element, {
-            'parent_url': re.escape(six.text_type(parent_key)),
+            'parent_url': re.escape(str(parent_key)),
             'index_in_children_list': re.escape(str(index_in_children_list)),
         })
 
@@ -496,11 +494,11 @@ class DraftPublishedOpBaseTestSetup(OLXFormatChecker, DraftPublishedOpTestCourse
     Setup base class for draft/published/OLX tests.
     """
 
-    EXPORTED_COURSE_BEFORE_DIR_NAME = u'exported_course_before'
-    EXPORTED_COURSE_AFTER_DIR_NAME = u'exported_course_after_{}'
+    EXPORTED_COURSE_BEFORE_DIR_NAME = 'exported_course_before'
+    EXPORTED_COURSE_AFTER_DIR_NAME = 'exported_course_after_{}'
 
     def setUp(self):
-        super(DraftPublishedOpBaseTestSetup, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.export_dir = self.EXPORTED_COURSE_BEFORE_DIR_NAME
         self.root_export_dir = None
         self.contentstore = None
@@ -564,7 +562,7 @@ class DraftPublishedOpBaseTestSetup(OLXFormatChecker, DraftPublishedOpTestCourse
         """
         Make a unique name for the new export dir.
         """
-        return self.EXPORTED_COURSE_AFTER_DIR_NAME.format(six.text_type(uuid.uuid4())[:8])
+        return self.EXPORTED_COURSE_AFTER_DIR_NAME.format(str(uuid.uuid4())[:8])
 
     def publish(self, block_list):
         """
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_semantics.py b/common/lib/xmodule/xmodule/modulestore/tests/test_semantics.py
index ba667f8588b6a609f92abe3a30f2ad3826422e0e..e5fcfbc10f1668e686f3faff1287bcc8c941991d 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_semantics.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_semantics.py
@@ -5,10 +5,10 @@ Tests of modulestore semantics: How do the interfaces methods of ModuleStore rel
 
 import itertools
 from collections import namedtuple
+from unittest.mock import patch
 
 import pytest
 import ddt
-from mock import patch
 from xblock.core import XBlock, XBlockAside
 from xblock.fields import Scope, String
 from xblock.runtime import DictKeyValueStore, KvsFieldData
@@ -59,7 +59,7 @@ class DirectOnlyCategorySemantics(PureModulestoreTestCase):
     ASIDE_DATA_FIELD = TestField('content', '<div>aside test data</div>', '<div>aside different test data</div>')
 
     def setUp(self):
-        super(DirectOnlyCategorySemantics, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.course = CourseFactory.create(
             org='test_org',
             number='999',
@@ -345,7 +345,7 @@ class DirectOnlyCategorySemantics(PureModulestoreTestCase):
             self.assertCourseSummaryFields(course_summaries)
 
             # Verify fetched accessible courses list is a list of CourseSummery instances
-            assert all((isinstance(course, CourseSummary) for course in course_summaries))
+            assert all(isinstance(course, CourseSummary) for course in course_summaries)
 
     @ddt.data(*itertools.product(['chapter', 'sequential'], [True, False]))
     @ddt.unpack
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_copy_from_template.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_copy_from_template.py
index 86eb5e0f312d37ad8490ac160a4c586ce841fa4b..2d0377ddfadd27112acbe3e743a3f5ca9dce1f91 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_copy_from_template.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_copy_from_template.py
@@ -6,7 +6,6 @@ However for these tests, we make sure it also works when copying from course to
 
 
 import ddt
-from six.moves import range
 import pytest
 
 from xmodule.modulestore import ModuleStoreEnum
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_migrator.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_migrator.py
index 60600ff79872507354a4302ea94c5a7773503dfb..a322e2b3962f1fb4025d0b0c9c1f17ed0a9d9462 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_migrator.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_migrator.py
@@ -6,10 +6,8 @@ Tests for split_migrator
 
 import random
 import uuid
+from unittest import mock
 
-import mock
-import six
-from six.moves import range, zip
 from xblock.fields import UNIQUE_ID, Reference, ReferenceList, ReferenceValueDict
 
 from openedx.core.lib.tests import attr
@@ -24,7 +22,7 @@ class TestMigration(SplitWMongoCourseBootstrapper):
     """
 
     def setUp(self):
-        super(TestMigration, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.migrator = SplitMigrator(self.split_mongo, self.draft_mongo)
 
     def _create_course(self):  # lint-amnesty, pylint: disable=arguments-differ
@@ -35,7 +33,7 @@ class TestMigration(SplitWMongoCourseBootstrapper):
         only the live ones get to published. Some are only draft, some are both, some are only live.
         * about, static_tab, and conditional documents
         """
-        super(TestMigration, self)._create_course(split=False)  # lint-amnesty, pylint: disable=super-with-arguments
+        super()._create_course(split=False)
 
         # chapters
         chapter1_name = uuid.uuid4().hex
@@ -167,7 +165,7 @@ class TestMigration(SplitWMongoCourseBootstrapper):
         if split_dag_root.category != 'course':
             assert presplit_dag_root.location.block_id == split_dag_root.location.block_id
         # compare all fields but references
-        for name, field in six.iteritems(presplit_dag_root.fields):
+        for name, field in presplit_dag_root.fields.items():
             # fields generated from UNIQUE_IDs are unique to an XBlock's scope,
             # so if such a field is unset on an XBlock, we don't expect it
             # to persist across courses
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
index 400c4df5be1c40b4bfde2b54af08496a75666dc1..977964067783c3111e3b94926d4f0d3a59ce93c9 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
@@ -9,17 +9,15 @@ import random
 import re
 import unittest
 from importlib import import_module
+from unittest.mock import patch
 
 import pytest
 import ddt
-import six
 from ccx_keys.locator import CCXBlockUsageLocator
 from contracts import contract
 from django.core.cache import InvalidCacheBackendError, caches
-from mock import patch
 from opaque_keys.edx.locator import BlockUsageLocator, CourseKey, CourseLocator, LocalId, VersionTree
 from path import Path as path
-from six.moves import range
 from xblock.fields import Reference, ReferenceList, ReferenceValueDict
 
 from openedx.core.lib import tempdir
@@ -58,7 +56,7 @@ class SplitModuleTest(unittest.TestCase):
     # Snippets of what would be in the django settings envs file
     DOC_STORE_CONFIG = {
         'host': MONGO_HOST,
-        'db': 'test_xmodule_{0}'.format(os.getpid()),
+        'db': f'test_xmodule_{os.getpid()}',
         'port': MONGO_PORT_NUM,
         'collection': 'modulestore',
     }
@@ -503,7 +501,7 @@ class SplitModuleTest(unittest.TestCase):
         '''
         Sets up the initial data into the db
         '''
-        for _course_id, course_spec in six.iteritems(SplitModuleTest.COURSE_CONTENT):
+        for _course_id, course_spec in SplitModuleTest.COURSE_CONTENT.items():
             course = split_store.create_course(
                 course_spec['org'],
                 course_spec['course'],
@@ -514,7 +512,7 @@ class SplitModuleTest(unittest.TestCase):
                 root_block_id=course_spec['root_block_id']
             )
             for revision in course_spec.get('revisions', []):
-                for (block_type, block_id), fields in six.iteritems(revision.get('update', {})):
+                for (block_type, block_id), fields in revision.get('update', {}).items():
                     # cheat since course is most frequent
                     if course.location.block_id == block_id:
                         block = course
@@ -522,7 +520,7 @@ class SplitModuleTest(unittest.TestCase):
                         # not easy to figure out the category but get_item won't care
                         block_usage = BlockUsageLocator.make_relative(course.location, block_type, block_id)
                         block = split_store.get_item(block_usage)
-                    for key, value in six.iteritems(fields):
+                    for key, value in fields.items():
                         setattr(block, key, value)
                 # create new blocks into dag: parent must already exist; thus, order is important
                 new_ele_dict = {}
@@ -551,7 +549,7 @@ class SplitModuleTest(unittest.TestCase):
         split_store.copy("test@edx.org", source_course, destination, [to_publish], None)
 
     def setUp(self):
-        super(SplitModuleTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.user_id = random.getrandbits(32)
 
     def tearDown(self):
@@ -562,7 +560,7 @@ class SplitModuleTest(unittest.TestCase):
             modulestore()._drop_database(database=False, connections=False)  # pylint: disable=protected-access
             # drop the modulestore to force re init
             SplitModuleTest.modulestore = None
-        super(SplitModuleTest, self).tearDown()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().tearDown()
 
     def findByIdInResult(self, collection, _id):  # pylint: disable=invalid-name
         """
@@ -953,7 +951,7 @@ class TestCourseStructureCache(SplitModuleTest):
             'org', 'course', 'test_run', self.user, BRANCH_NAME_DRAFT,
         )
 
-        super(TestCourseStructureCache, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
     @patch('xmodule.modulestore.split_mongo.mongo_connection.get_cache')
     def test_course_structure_cache(self, mock_get_cache):
@@ -1741,8 +1739,8 @@ class TestItemCrud(SplitModuleTest):
             # First child should have been moved to second position, and better child takes the lead
             refetch_course = store.get_course(versionless_course_locator)
             children = refetch_course.get_children()
-            assert six.text_type(children[1].location) == six.text_type(first_child.location)
-            assert six.text_type(children[0].location) == six.text_type(second_child.location)
+            assert str(children[1].location) == str(first_child.location)
+            assert str(children[0].location) == str(second_child.location)
 
             # Clean up the data so we don't break other tests which apparently expect a particular state
             store.delete_course(refetch_course.id, user)
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore_bulk_operations.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore_bulk_operations.py
index d577876aa196159ac640c10547aee450a5987edc..e6070576f0322e6014b30c185a9a875ad2bb8506 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore_bulk_operations.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore_bulk_operations.py
@@ -6,20 +6,18 @@ Tests for bulk operations in Split Modulestore.
 
 import copy
 import unittest
+from unittest.mock import MagicMock, Mock, call
 
-import six
 import ddt
 from bson.objectid import ObjectId
-from mock import MagicMock, Mock, call
 from opaque_keys.edx.locator import CourseLocator
-from six.moves import range
 
 from xmodule.modulestore.split_mongo.mongo_connection import MongoConnection
 from xmodule.modulestore.split_mongo.split import SplitBulkWriteMixin
 
 VERSION_GUID_DICT = {
     'SAMPLE_VERSION_GUID': 'deadbeef1234' * 2,
-    'SAMPLE_UNICODE_VERSION_GUID': u'deadbeef1234' * 2,
+    'SAMPLE_UNICODE_VERSION_GUID': 'deadbeef1234' * 2,
     'BSON_OBJECTID': ObjectId()
 }
 SAMPLE_GUIDS_LIST = ['SAMPLE_VERSION_GUID', 'SAMPLE_UNICODE_VERSION_GUID', 'BSON_OBJECTID']
@@ -28,7 +26,7 @@ SAMPLE_GUIDS_LIST = ['SAMPLE_VERSION_GUID', 'SAMPLE_UNICODE_VERSION_GUID', 'BSON
 class TestBulkWriteMixin(unittest.TestCase):  # lint-amnesty, pylint: disable=missing-class-docstring
 
     def setUp(self):
-        super(TestBulkWriteMixin, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.bulk = SplitBulkWriteMixin()
         self.bulk.SCHEMA_VERSION = 1
         self.clear_cache = self.bulk._clear_cache = Mock(name='_clear_cache')
@@ -53,7 +51,7 @@ class TestBulkWriteMixinPreviousTransaction(TestBulkWriteMixin):
     Verify that opening and closing a transaction doesn't affect later behaviour.
     """
     def setUp(self):
-        super(TestBulkWriteMixinPreviousTransaction, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.bulk._begin_bulk_operation(self.course_key)
         self.bulk.insert_course_index(self.course_key, MagicMock('prev-index-entry'))
         self.bulk.update_structure(self.course_key, {'this': 'is', 'the': 'previous structure', '_id': ObjectId()})
@@ -170,8 +168,7 @@ class TestBulkWriteMixinClosed(TestBulkWriteMixin):
         self.bulk.update_structure(self.course_key.replace(branch='b'), other_structure)
         self.assertConnCalls()
         self.bulk._end_bulk_operation(self.course_key)
-        six.assertCountEqual(
-            self,
+        self.assertCountEqual(
             [
                 call.insert_structure(self.structure, self.course_key),
                 call.insert_structure(other_structure, self.course_key)
@@ -207,8 +204,7 @@ class TestBulkWriteMixinClosed(TestBulkWriteMixin):
         self.bulk.update_definition(self.course_key.replace(branch='b'), other_definition)
         self.bulk.insert_course_index(self.course_key, {'versions': {'a': self.definition['_id'], 'b': other_definition['_id']}})  # lint-amnesty, pylint: disable=line-too-long
         self.bulk._end_bulk_operation(self.course_key)
-        six.assertCountEqual(
-            self,
+        self.assertCountEqual(
             [
                 call.insert_definition(self.definition, self.course_key),
                 call.insert_definition(other_definition, self.course_key),
@@ -239,8 +235,7 @@ class TestBulkWriteMixinClosed(TestBulkWriteMixin):
         self.bulk.update_definition(self.course_key.replace(branch='b'), other_definition)
         self.assertConnCalls()
         self.bulk._end_bulk_operation(self.course_key)
-        six.assertCountEqual(
-            self,
+        self.assertCountEqual(
             [
                 call.insert_definition(self.definition, self.course_key),
                 call.insert_definition(other_definition, self.course_key)
@@ -276,8 +271,7 @@ class TestBulkWriteMixinClosed(TestBulkWriteMixin):
         self.bulk.update_structure(self.course_key.replace(branch='b'), other_structure)
         self.bulk.insert_course_index(self.course_key, {'versions': {'a': self.structure['_id'], 'b': other_structure['_id']}})  # lint-amnesty, pylint: disable=line-too-long
         self.bulk._end_bulk_operation(self.course_key)
-        six.assertCountEqual(
-            self,
+        self.assertCountEqual(
             [
                 call.insert_structure(self.structure, self.course_key),
                 call.insert_structure(other_structure, self.course_key),
@@ -385,7 +379,7 @@ class TestBulkWriteMixinFindMethods(TestBulkWriteMixin):
     def test_find_matching_course_indexes(self, branch, search_targets, matching, unmatching):
         db_indexes = [{'org': 'what', 'course': 'this', 'run': 'needs'}]
         for n, index in enumerate(matching + unmatching):
-            course_key = CourseLocator('org', 'course', 'run{}'.format(n))
+            course_key = CourseLocator('org', 'course', f'run{n}')
             self.bulk._begin_bulk_operation(course_key)
             for attr in ['org', 'course', 'run']:
                 index[attr] = getattr(course_key, attr)
@@ -394,7 +388,7 @@ class TestBulkWriteMixinFindMethods(TestBulkWriteMixin):
         expected = matching + db_indexes
         self.conn.find_matching_course_indexes.return_value = db_indexes
         result = self.bulk.find_matching_course_indexes(branch, search_targets)
-        six.assertCountEqual(self, result, expected)
+        self.assertCountEqual(result, expected)
         for item in unmatching:
             assert item not in result
 
@@ -419,7 +413,7 @@ class TestBulkWriteMixinFindMethods(TestBulkWriteMixin):
 
         db_structures = [db_structure(_id) for _id in db_ids if _id not in active_ids]
         for n, _id in enumerate(active_ids):
-            course_key = CourseLocator('org', 'course', 'run{}'.format(n))
+            course_key = CourseLocator('org', 'course', f'run{n}')
             self.bulk._begin_bulk_operation(course_key)
             self.bulk.update_structure(course_key, active_structure(_id))
 
@@ -515,7 +509,7 @@ class TestBulkWriteMixinFindMethods(TestBulkWriteMixin):
         db_structures = [db_structure(_id) for _id in db_ids]
         active_structures = []
         for n, _id in enumerate(active_ids):
-            course_key = CourseLocator('org', 'course', 'run{}'.format(n))
+            course_key = CourseLocator('org', 'course', f'run{n}')
             self.bulk._begin_bulk_operation(course_key)
             structure = active_structure(_id)
             self.bulk.update_structure(course_key, structure)
@@ -575,14 +569,14 @@ class TestBulkWriteMixinFindMethods(TestBulkWriteMixin):
             structure.setdefault('_id', ObjectId())
 
         for n, structure in enumerate(active_match + active_unmatch):
-            course_key = CourseLocator('org', 'course', 'run{}'.format(n))
+            course_key = CourseLocator('org', 'course', f'run{n}')
             self.bulk._begin_bulk_operation(course_key)
             self.bulk.update_structure(course_key, structure)
 
         self.conn.find_ancestor_structures.return_value = db_match + db_unmatch
         results = self.bulk.find_ancestor_structures(original_version, block_id)
         self.conn.find_ancestor_structures.assert_called_once_with(original_version, block_id)
-        six.assertCountEqual(self, active_match + db_match, results)
+        self.assertCountEqual(active_match + db_match, results)
 
 
 @ddt.ddt
@@ -592,7 +586,7 @@ class TestBulkWriteMixinOpen(TestBulkWriteMixin):
     """
 
     def setUp(self):
-        super(TestBulkWriteMixinOpen, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.bulk._begin_bulk_operation(self.course_key)
 
     @ddt.data(*SAMPLE_GUIDS_LIST)
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_mongo_mongo_connection.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_mongo_mongo_connection.py
index 7512c3da004cbdaa354c140c35c2a0dc8a4c5638..3460470186b3fe93aec04b8f7768338756f1392a 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_mongo_mongo_connection.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_mongo_mongo_connection.py
@@ -2,8 +2,9 @@
 
 
 import unittest
+from unittest.mock import patch
+
 import pytest
-from mock import patch
 from pymongo.errors import ConnectionFailure
 
 from xmodule.exceptions import HeartbeatFailure
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py
index e32a517e00682de52868cda80a72528a40984f59..7cd1537cfa52c151f98e13d4391858916625d025 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py
@@ -4,10 +4,9 @@ import datetime
 import os
 import random
 import unittest
+from unittest import mock
 
-import mock
 import pytest
-import six
 from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
 
 from xmodule.modulestore import ModuleStoreEnum
@@ -38,7 +37,7 @@ class SplitWMongoCourseBootstrapper(unittest.TestCase):
     db_config = {
         'host': MONGO_HOST,
         'port': MONGO_PORT_NUM,
-        'db': 'test_xmodule_{}'.format(os.getpid()),
+        'db': f'test_xmodule_{os.getpid()}',
         'collection': 'modulestore'
     }
 
@@ -53,7 +52,7 @@ class SplitWMongoCourseBootstrapper(unittest.TestCase):
 
     def setUp(self):
         self.user_id = random.getrandbits(32)
-        super(SplitWMongoCourseBootstrapper, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.split_mongo = SplitMongoModuleStore(
             None,
             self.db_config,
@@ -90,7 +89,7 @@ class SplitWMongoCourseBootstrapper(unittest.TestCase):
         )
         if not draft:
             self.draft_mongo.publish(location, self.user_id)
-        if isinstance(data, six.string_types):
+        if isinstance(data, str):
             fields = {'data': data}
         else:
             fields = data.copy()
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_store_utilities.py b/common/lib/xmodule/xmodule/modulestore/tests/test_store_utilities.py
index 166c633e6223f2d1dba1abe204637a841e0eab2f..fdc76655f7705f2f216d205d8b93ca721a05cadb 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_store_utilities.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_store_utilities.py
@@ -4,9 +4,9 @@ Tests for store_utilities.py
 
 
 import unittest
+from unittest.mock import Mock
 
 import ddt
-from mock import Mock
 
 from xmodule.modulestore.store_utilities import draft_node_constructor, get_draft_subtree_roots
 
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_xml.py b/common/lib/xmodule/xmodule/modulestore/tests/test_xml.py
index bbd47227c565f89dc69a0f0d6171e98cfa39d5bd..9b59cabb46a6e07db29460109fa61c3bd41717e1 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_xml.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_xml.py
@@ -6,9 +6,10 @@ well-formed and not-well-formed XML.
 
 import os.path
 from glob import glob
+from unittest.mock import Mock, patch
+
 import pytest
 from django.test import TestCase
-from mock import Mock, patch
 from opaque_keys.edx.keys import CourseKey
 from opaque_keys.edx.locator import CourseLocator
 
@@ -145,7 +146,7 @@ class TestModuleStoreIgnore(TestXMLModuleStore):  # lint-amnesty, pylint: disabl
     course_dir = DATA_DIR / "course_ignore"
 
     def setUp(self):
-        super(TestModuleStoreIgnore, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.addCleanup(remove_temp_files_from_list, list(TILDA_FILES_DICT.keys()), self.course_dir / "static")
         add_temp_files_from_dict(TILDA_FILES_DICT, self.course_dir / "static")
 
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py b/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py
index b702a574b1e7426f41c62f391d2a97058610f91d..6e0e69dc861bd3594173110675b79367c0a1960b 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py
@@ -7,9 +7,9 @@ import importlib
 import os
 import unittest
 from uuid import uuid4
+from unittest import mock
+
 import pytest
-import mock
-import six
 from opaque_keys.edx.keys import CourseKey
 from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
 from path import Path as path
@@ -23,10 +23,7 @@ from xmodule.modulestore.xml_importer import StaticContentImporter, _update_and_
 from xmodule.tests import DATA_DIR
 from xmodule.x_module import XModuleMixin
 
-if six.PY2:
-    OPEN_BUILTIN = '__builtin__.open'
-else:
-    OPEN_BUILTIN = 'builtins.open'
+OPEN_BUILTIN = 'builtins.open'
 
 
 class ModuleStoreNoSettings(unittest.TestCase):
@@ -72,7 +69,7 @@ class ModuleStoreNoSettings(unittest.TestCase):
         Add cleanups
         """
         self.addCleanup(self.cleanup_modulestore)
-        super(ModuleStoreNoSettings, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
 
 #===========================================
@@ -141,7 +138,7 @@ class RemapNamespaceTest(ModuleStoreNoSettings):
         self.field_data = KvsFieldData(kvs=DictKeyValueStore())
         self.scope_ids = ScopeIds('Bob', 'stubxblock', '123', 'import')
         self.xblock = StubXBlock(self.runtime, self.field_data, self.scope_ids)
-        super(RemapNamespaceTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
     def test_remap_namespace_native_xblock(self):
 
@@ -282,7 +279,7 @@ class UpdateLocationTest(ModuleStoreNoSettings):
             BlockUsageLocator(CourseLocator('org', 'course', 'run'), 'mutablestubxblock', 'child2'),
         ]
 
-        super(UpdateLocationTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
     def _check_explicitly_set(self, block, scope, expected_explicitly_set_fields, should_be_set=False):
         """ Gets fields that are explicitly set on block and checks if they are marked as explicitly set or not """
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/utils.py b/common/lib/xmodule/xmodule/modulestore/tests/utils.py
index deda16f3e214dab7b3a9e710c0b703db51740efa..5208ad183c542340a2826ea24e88159d21b972d2 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/utils.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/utils.py
@@ -12,10 +12,8 @@ from tempfile import mkdtemp
 from unittest import TestCase
 from uuid import uuid4
 
-import six
 from contextlib2 import ExitStack
 from path import Path as path
-from six.moves import range, zip
 
 from xmodule.contentstore.mongo import MongoContentStore
 from xmodule.modulestore.draft_and_published import ModuleStoreDraftAndPublished
@@ -84,10 +82,10 @@ def add_temp_files_from_dict(file_dict, dir):  # lint-amnesty, pylint: disable=r
     Takes in a dict formatted as: { file_name: content }, and adds files to directory
     """
     for file_name in file_dict:
-        with io.open("{}/{}".format(dir, file_name), "w") as opened_file:
+        with open(f"{dir}/{file_name}", "w") as opened_file:
             content = file_dict[file_name]
             if content:
-                opened_file.write(six.text_type(content))
+                opened_file.write(str(content))
 
 
 def remove_temp_files_from_list(file_list, dir):  # lint-amnesty, pylint: disable=redefined-builtin
@@ -95,7 +93,7 @@ def remove_temp_files_from_list(file_list, dir):  # lint-amnesty, pylint: disabl
     Takes in a list of file names and removes them from dir if they exist
     """
     for file_name in file_list:
-        file_path = "{}/{}".format(dir, file_name)
+        file_path = f"{dir}/{file_name}"
         if os.path.exists(file_path):
             os.remove(file_path)
 
@@ -105,7 +103,7 @@ class MixedSplitTestCase(TestCase):
     Stripped-down version of ModuleStoreTestCase that can be used without Django
     (i.e. for testing in common/lib/ ). Sets up MixedModuleStore and Split.
     """
-    RENDER_TEMPLATE = lambda t_n, d, ctx=None, nsp='main': u'{}: {}, {}'.format(t_n, repr(d), repr(ctx))
+    RENDER_TEMPLATE = lambda t_n, d, ctx=None, nsp='main': '{}: {}, {}'.format(t_n, repr(d), repr(ctx))
     modulestore_options = {
         'default_class': 'xmodule.raw_module.RawDescriptor',
         'fs_root': DATA_DIR,
@@ -115,7 +113,7 @@ class MixedSplitTestCase(TestCase):
     DOC_STORE_CONFIG = {
         'host': MONGO_HOST,
         'port': MONGO_PORT_NUM,
-        'db': 'test_mongo_libs_{0}'.format(os.getpid()),
+        'db': f'test_mongo_libs_{os.getpid()}',
         'collection': 'modulestore',
         'asset_collection': 'assetstore',
     }
@@ -134,7 +132,7 @@ class MixedSplitTestCase(TestCase):
         """
         Set up requirements for testing: a user ID and a modulestore
         """
-        super(MixedSplitTestCase, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.user_id = ModuleStoreEnum.UserID.test
 
         self.store = MixedModuleStore(
@@ -162,7 +160,7 @@ class MixedSplitTestCase(TestCase):
         )
 
 
-class ProceduralCourseTestMixin(object):
+class ProceduralCourseTestMixin:
     """
     Contains methods for testing courses generated procedurally
     """
@@ -193,7 +191,7 @@ class ProceduralCourseTestMixin(object):
             descend(self.course, ['chapter', 'sequential', 'vertical', 'problem'])
 
 
-class MemoryCache(object):
+class MemoryCache:
     """
     This fits the metadata_inheritance_cache_subsystem interface used by
     the modulestore, and stores the data in a dictionary in memory.
@@ -222,7 +220,7 @@ class MemoryCache(object):
         self.data[key] = value
 
 
-class MongoContentstoreBuilder(object):
+class MongoContentstoreBuilder:
     """
     A builder class for a MongoContentStore.
     """
@@ -233,7 +231,7 @@ class MongoContentstoreBuilder(object):
         when the context closes.
         """
         contentstore = MongoContentStore(
-            db='contentstore{}'.format(THIS_UUID),
+            db=f'contentstore{THIS_UUID}',
             collection='content',
             **COMMON_DOCSTORE_CONFIG
         )
@@ -249,7 +247,7 @@ class MongoContentstoreBuilder(object):
         return 'MongoContentstoreBuilder()'
 
 
-class StoreBuilderBase(object):
+class StoreBuilderBase:
     """
     Base class for all modulestore builders.
     """
@@ -291,7 +289,7 @@ class MongoModulestoreBuilder(StoreBuilderBase):
                 all of its assets.
         """
         doc_store_config = dict(
-            db='modulestore{}'.format(THIS_UUID),
+            db=f'modulestore{THIS_UUID}',
             collection='xmodule',
             asset_collection='asset_metadata',
             **COMMON_DOCSTORE_CONFIG
@@ -339,7 +337,7 @@ class VersioningModulestoreBuilder(StoreBuilderBase):
                 all of its assets.
         """
         doc_store_config = dict(
-            db='modulestore{}'.format(THIS_UUID),
+            db=f'modulestore{THIS_UUID}',
             collection='split_module',
             **COMMON_DOCSTORE_CONFIG
         )
@@ -440,7 +438,7 @@ class MixedModulestoreBuilder(StoreBuilderBase):
             yield self.mixed_modulestore
 
     def __repr__(self):
-        return 'MixedModulestoreBuilder({!r}, {!r})'.format(self.store_builders, self.mappings)
+        return f'MixedModulestoreBuilder({self.store_builders!r}, {self.mappings!r})'
 
     def asset_collection(self):
         """
@@ -519,7 +517,7 @@ class PureModulestoreTestCase(TestCase):
     MODULESTORE = None
 
     def setUp(self):
-        super(PureModulestoreTestCase, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
         builder = self.MODULESTORE.build()
         self.assets, self.store = builder.__enter__()
diff --git a/common/lib/xmodule/xmodule/modulestore/xml.py b/common/lib/xmodule/xmodule/modulestore/xml.py
index 3e5322375041ab163d1b1037af5c81e953d2bcfe..68635e72eb7cb8c615c525826e9c6478e01a5564 100644
--- a/common/lib/xmodule/xmodule/modulestore/xml.py
+++ b/common/lib/xmodule/xmodule/modulestore/xml.py
@@ -13,7 +13,6 @@ from collections import defaultdict
 from contextlib import contextmanager
 from importlib import import_module
 
-import six
 from django.utils.encoding import python_2_unicode_compatible
 from edx_django_utils.monitoring import set_custom_attribute
 from fs.osfs import OSFS
@@ -128,9 +127,9 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):  # lint-amnesty, pyl
                     # put it in the error tracker--content folks need to see it.
 
                     if tag in need_uniq_names:
-                        error_tracker(u"PROBLEM: no name of any kind specified for {tag}.  Student "
-                                      u"state will not be properly tracked for this module.  Problem xml:"
-                                      u" '{xml}...'".format(tag=tag, xml=xml[:100]))
+                        error_tracker("PROBLEM: no name of any kind specified for {tag}.  Student "
+                                      "state will not be properly tracked for this module.  Problem xml:"
+                                      " '{xml}...'".format(tag=tag, xml=xml[:100]))
                     else:
                         # TODO (vshnayder): We may want to enable this once course repos are cleaned up.
                         # (or we may want to give up on the requirement for non-state-relevant issues...)
@@ -143,8 +142,8 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):  # lint-amnesty, pyl
                     # doesn't store state, don't complain about things that are
                     # hashed.
                     if tag in need_uniq_names:
-                        msg = (u"Non-unique url_name in xml.  This may break state tracking for content."
-                               u"  url_name={0}.  Content={1}".format(url_name, xml[:100]))
+                        msg = ("Non-unique url_name in xml.  This may break state tracking for content."
+                               "  url_name={}.  Content={}".format(url_name, xml[:100]))
                         error_tracker("PROBLEM: " + msg)
                         log.warning(msg)
                         # Just set name to fallback_name--if there are multiple things with the same fallback name,
@@ -181,14 +180,14 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):  # lint-amnesty, pyl
                 msg = "Error loading from xml. %s"
                 log.warning(
                     msg,
-                    six.text_type(err)[:200],
+                    str(err)[:200],
                     # Normally, we don't want lots of exception traces in our logs from common
                     # content problems.  But if you're debugging the xml loading code itself,
                     # uncomment the next line.
                     # exc_info=True
                 )
 
-                msg = msg % (six.text_type(err)[:200])
+                msg = msg % (str(err)[:200])
 
                 self.error_tracker(msg)
                 err_msg = msg + "\n" + exc_info_to_str(sys.exc_info())
@@ -221,7 +220,7 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):  # lint-amnesty, pyl
             descriptor.save()
             return descriptor
 
-        render_template = lambda template, context: u''
+        render_template = lambda template, context: ''
 
         # TODO (vshnayder): we are somewhat architecturally confused in the loading code:
         # load_item should actually be get_instance, because it expects the course-specific
@@ -234,7 +233,7 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):  # lint-amnesty, pyl
 
         id_manager = CourseImportLocationManager(course_id, target_course_id)
 
-        super(ImportSystem, self).__init__(  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__(
             load_item=load_item,
             resources_fs=resources_fs,
             render_template=render_template,
@@ -258,7 +257,7 @@ class CourseLocationManager(OpaqueKeyReader, AsideKeyGenerator):
     based within a course
     """
     def __init__(self, course_id):
-        super(CourseLocationManager, self).__init__()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__()
         self.course_id = course_id
         self.autogen_ids = itertools.count(0)
 
@@ -298,7 +297,7 @@ class CourseImportLocationManager(CourseLocationManager):
     see https://openedx.atlassian.net/browse/MA-417 as a pending TODO.
     """
     def __init__(self, course_id, target_course_id):
-        super(CourseImportLocationManager, self).__init__(course_id=course_id)  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__(course_id=course_id)
         self.target_course_id = target_course_id
 
 
@@ -326,7 +325,7 @@ class XMLModuleStore(ModuleStoreReadBase):
             source_dirs or course_ids (list of str): If specified, the list of source_dirs or course_ids to load.
                 Otherwise, load all courses. Note, providing both
         """
-        super(XMLModuleStore, self).__init__(**kwargs)  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__(**kwargs)
 
         self.data_dir = path(data_dir)
         self.modules = defaultdict(dict)  # course_id -> dict(location -> XBlock)
@@ -378,10 +377,10 @@ class XMLModuleStore(ModuleStoreReadBase):
         try:
             course_descriptor = self.load_course(course_dir, course_ids, errorlog.tracker, target_course_id)
         except Exception as exc:  # pylint: disable=broad-except
-            msg = "ERROR: Failed to load courselike '{0}': {1}".format(
-                course_dir.encode("utf-8"), six.text_type(exc)
+            msg = "ERROR: Failed to load courselike '{}': {}".format(
+                course_dir.encode("utf-8"), str(exc)
             )
-            set_custom_attribute('course_import_failure', "Courselike load failure: {}".format(msg))
+            set_custom_attribute('course_import_failure', f"Courselike load failure: {msg}")
             log.exception(msg)
             errorlog.tracker(msg)
             self.errored_courses[course_dir] = errorlog
@@ -424,8 +423,8 @@ class XMLModuleStore(ModuleStoreReadBase):
         try:
             with open(policy_path) as f:
                 return json.load(f)
-        except (IOError, ValueError) as err:
-            msg = "ERROR: loading courselike policy from {0}".format(policy_path)
+        except (OSError, ValueError) as err:
+            msg = f"ERROR: loading courselike policy from {policy_path}"
             tracker(msg)
             log.warning(msg + " " + str(err))  # lint-amnesty, pylint: disable=logging-not-lazy
         return {}
@@ -478,7 +477,7 @@ class XMLModuleStore(ModuleStoreReadBase):
 
                 # VS[compat]: remove once courses use the policy dirs.
                 if policy == {}:
-                    old_policy_path = self.data_dir / course_dir / 'policies' / '{0}.json'.format(url_name)
+                    old_policy_path = self.data_dir / course_dir / 'policies' / f'{url_name}.json'
                     policy = self.load_policy(old_policy_path, tracker)
             else:
                 policy = {}
@@ -608,7 +607,7 @@ class XMLModuleStore(ModuleStoreReadBase):
                 with open(file_path) as field_content_file:
                     field_data = json.load(field_content_file)
                     data_content = {field: field_data}
-        except (IOError, ValueError):
+        except (OSError, ValueError):
             # ignore this exception
             # only new exported courses which use content fields other than 'metadata' and 'data'
             # will have this file '{dirname}.{field_name}.json'
@@ -627,7 +626,7 @@ class XMLModuleStore(ModuleStoreReadBase):
             if filepath.endswith('~'):  # skip *~ files
                 continue
 
-            with io.open(filepath) as f:
+            with open(filepath) as f:
                 try:
                     if filepath.find('.json') != -1:
                         # json file with json data content
@@ -638,7 +637,7 @@ class XMLModuleStore(ModuleStoreReadBase):
                             try:
                                 # get and update data field in xblock runtime
                                 module = system.load_item(loc)
-                                for key, value in six.iteritems(data_content):
+                                for key, value in data_content.items():
                                     setattr(module, key, value)
                                 module.save()
                             except ItemNotFoundError:
@@ -681,8 +680,8 @@ class XMLModuleStore(ModuleStoreReadBase):
                         self.modules[course_descriptor.id][module.scope_ids.usage_id] = module
                 except Exception as exc:  # pylint: disable=broad-except
                     logging.exception("Failed to load %s. Skipping... \
-                            Exception: %s", filepath, six.text_type(exc))
-                    system.error_tracker("ERROR: " + six.text_type(exc))
+                            Exception: %s", filepath, str(exc))
+                    system.error_tracker("ERROR: " + str(exc))
 
     def has_item(self, usage_key):
         """
@@ -756,7 +755,7 @@ class XMLModuleStore(ModuleStoreReadBase):
                 for fields in [settings, content, qualifiers]
             )
 
-        for mod_loc, module in six.iteritems(self.modules[course_id]):
+        for mod_loc, module in self.modules[course_id].items():
             if _block_matches_all(mod_loc, module):
                 items.append(module)
 
@@ -796,7 +795,7 @@ class XMLModuleStore(ModuleStoreReadBase):
         Return a dictionary of course_dir -> [(msg, exception_str)], for each
         course_dir where course loading failed.
         """
-        return dict((k, self.errored_courses[k].errors) for k in self.errored_courses)
+        return {k: self.errored_courses[k].errors for k in self.errored_courses}
 
     def get_orphans(self, course_key, **kwargs):
         """
@@ -847,7 +846,7 @@ class XMLModuleStore(ModuleStoreReadBase):
         A context manager for temporarily setting the branch value for the store to the given branch_setting.
         """
         if branch_setting != ModuleStoreEnum.Branch.published_only:
-            raise ValueError(u"Cannot set branch setting to {} on a ReadOnly store".format(branch_setting))
+            raise ValueError(f"Cannot set branch setting to {branch_setting} on a ReadOnly store")
         yield
 
     def _find_course_asset(self, asset_key):
diff --git a/common/lib/xmodule/xmodule/modulestore/xml_exporter.py b/common/lib/xmodule/xmodule/modulestore/xml_exporter.py
index cfbfa810d69a015fa9a62dbb8e97bb073dae3fde..767be91cffd52a5a7fe2fdad4029bcbe5c3be454 100644
--- a/common/lib/xmodule/xmodule/modulestore/xml_exporter.py
+++ b/common/lib/xmodule/xmodule/modulestore/xml_exporter.py
@@ -9,10 +9,8 @@ from abc import abstractmethod
 from json import dumps
 
 import lxml.etree
-import six
 from fs.osfs import OSFS
 from opaque_keys.edx.locator import CourseLocator, LibraryLocator
-from six import text_type
 from xblock.fields import Reference, ReferenceList, ReferenceValueDict, Scope
 
 from xmodule.assetstore import AssetMetadata
@@ -60,12 +58,12 @@ def _export_drafts(modulestore, course_key, export_fs, xml_centric_course_key):
                 # if module has no parent, set its parent_url to `None`
                 parent_url = None
                 if parent_loc is not None:
-                    parent_url = text_type(parent_loc)
+                    parent_url = str(parent_loc)
 
                 draft_node = draft_node_constructor(
                     draft_module,
                     location=draft_module.location,
-                    url=text_type(draft_module.location),
+                    url=str(draft_module.location),
                     parent_location=parent_loc,
                     parent_url=parent_url,
                 )
@@ -103,7 +101,7 @@ def _export_drafts(modulestore, course_key, export_fs, xml_centric_course_key):
                 draft_node.module.add_xml_to_node(node)
 
 
-class ExportManager(object):
+class ExportManager:
     """
     Manages XML exporting for courselike objects.
     """
@@ -121,7 +119,7 @@ class ExportManager(object):
         self.contentstore = contentstore
         self.courselike_key = courselike_key
         self.root_dir = root_dir
-        self.target_dir = text_type(target_dir)
+        self.target_dir = str(target_dir)
 
     @abstractmethod
     def get_key(self):
@@ -200,7 +198,7 @@ class CourseExportManager(ExportManager):
         return self.modulestore.get_course(self.courselike_key, depth=None, lazy=False)
 
     def process_root(self, root, export_fs):
-        with export_fs.open(u'course.xml', 'wb') as course_xml:
+        with export_fs.open('course.xml', 'wb') as course_xml:
             lxml.etree.ElementTree(root).write(course_xml, encoding='utf-8')
 
     def process_extra(self, root, courselike, root_courselike_dir, xml_centric_courselike_key, export_fs):
@@ -242,7 +240,7 @@ class CourseExportManager(ExportManager):
                     output_dir = root_courselike_dir + '/static/images/'
                     if not os.path.isdir(output_dir):
                         os.makedirs(output_dir)
-                    with OSFS(output_dir).open(u'course_image.jpg', 'wb') as course_image_file:
+                    with OSFS(output_dir).open('course_image.jpg', 'wb') as course_image_file:
                         course_image_file.write(course_image.data)
 
         # export the static tabs
@@ -273,12 +271,12 @@ class CourseExportManager(ExportManager):
         course_run_policy_dir = policies_dir.makedir(course_policy_dir_name, recreate=True)
 
         # export the grading policy
-        with course_run_policy_dir.open(u'grading_policy.json', 'wb') as grading_policy:
+        with course_run_policy_dir.open('grading_policy.json', 'wb') as grading_policy:
             grading_policy.write(dumps(courselike.grading_policy, cls=EdxJSONEncoder,
                                        sort_keys=True, indent=4).encode('utf-8'))
 
         # export all of the course metadata in policy.json
-        with course_run_policy_dir.open(u'policy.json', 'wb') as course_policy:
+        with course_run_policy_dir.open('policy.json', 'wb') as course_policy:
             policy = {'course/' + courselike.location.run: own_metadata(courselike)}
             course_policy.write(dumps(policy, cls=EdxJSONEncoder, sort_keys=True, indent=4).encode('utf-8'))
 
@@ -357,7 +355,7 @@ def adapt_references(subtree, destination_course_key, export_fs):
     Map every reference in the subtree into destination_course_key and set it back into the xblock fields
     """
     subtree.runtime.export_fs = export_fs  # ensure everything knows where it's going!
-    for field_name, field in six.iteritems(subtree.fields):
+    for field_name, field in subtree.fields.items():
         if field.is_set_on(subtree):
             if isinstance(field, Reference):
                 value = field.read_from(subtree)
@@ -374,7 +372,7 @@ def adapt_references(subtree, destination_course_key, export_fs):
             elif isinstance(field, ReferenceValueDict):
                 field.write_to(
                     subtree, {
-                        key: ele.map_into_course(destination_course_key) for key, ele in six.iteritems(field.read_from(subtree))  # lint-amnesty, pylint: disable=line-too-long
+                        key: ele.map_into_course(destination_course_key) for key, ele in field.read_from(subtree).items()  # lint-amnesty, pylint: disable=line-too-long
                     }
                 )
 
@@ -388,7 +386,7 @@ def _export_field_content(xblock_item, item_dir):
         for field_name in module_data:
             if field_name not in DEFAULT_CONTENT_FIELDS:
                 # filename format: {dirname}.{field_name}.json
-                with item_dir.open(u'{0}.{1}.{2}'.format(xblock_item.location.block_id, field_name, 'json'),
+                with item_dir.open('{}.{}.{}'.format(xblock_item.location.block_id, field_name, 'json'),
                                    'wb') as field_content_file:
                     field_content_file.write(dumps(module_data.get(field_name, {}), cls=EdxJSONEncoder,
                                                    sort_keys=True, indent=4).encode('utf-8'))
diff --git a/common/lib/xmodule/xmodule/modulestore/xml_importer.py b/common/lib/xmodule/xmodule/modulestore/xml_importer.py
index 3e586728ecb80fc1569aaa29832a10f50a0bcf07..24194131af3d25d795609ac87c4ac5df2e0f4288 100644
--- a/common/lib/xmodule/xmodule/modulestore/xml_importer.py
+++ b/common/lib/xmodule/xmodule/modulestore/xml_importer.py
@@ -30,7 +30,6 @@ import os
 import re
 from abc import abstractmethod
 
-import six
 import xblock
 from edx_django_utils.monitoring import set_custom_attribute
 from lxml import etree
@@ -92,7 +91,7 @@ class StaticContentImporter:  # lint-amnesty, pylint: disable=missing-class-docs
         try:
             with open(course_data_path / 'policies/assets.json') as f:
                 self.policy = json.load(f)
-        except (IOError, ValueError) as err:  # lint-amnesty, pylint: disable=unused-variable
+        except (OSError, ValueError) as err:  # lint-amnesty, pylint: disable=unused-variable
             # xml backed courses won't have this file, only exported courses;
             # so, its absence is not really an exception.
             self.policy = {}
@@ -132,7 +131,7 @@ class StaticContentImporter:  # lint-amnesty, pylint: disable=missing-class-docs
         try:
             with open(full_file_path, 'rb') as f:
                 data = f.read()
-        except IOError:
+        except OSError:
             # OS X "companion files". See
             # http://www.diigo.com/annotated/0c936fda5da4aa1159c189cea227e174
             if filename.startswith('._'):
@@ -174,14 +173,14 @@ class StaticContentImporter:  # lint-amnesty, pylint: disable=missing-class-docs
         try:
             self.static_content_store.save(content)
         except Exception as err:  # lint-amnesty, pylint: disable=broad-except
-            msg = "Error importing {0}, error={1}".format(file_subpath, err)
+            msg = f"Error importing {file_subpath}, error={err}"
             log.exception(msg)
-            set_custom_attribute('course_import_failure', "Static Content Save Failure: {}".format(msg))
+            set_custom_attribute('course_import_failure', f"Static Content Save Failure: {msg}")
 
         return file_subpath, asset_key
 
 
-class ImportManager(object):
+class ImportManager:
     """
     Import xml-based courselikes from data_dir into modulestore.
 
@@ -352,7 +351,7 @@ class ImportManager(object):
                     asset_md = AssetMetadata(asset_key)
                     asset_md.from_xml(asset)
                     all_assets.append(asset_md)
-        except IOError:
+        except OSError:
             logging.info('No %s file is present with asset metadata.', assets_filename)
             return
         except Exception:  # pylint: disable=W0703
@@ -378,7 +377,7 @@ class ImportManager(object):
         # first into the store
         course_data_path = path(self.data_dir) / source_courselike.data_dir
 
-        log.debug(u'======> IMPORTING courselike %s', courselike_key)
+        log.debug('======> IMPORTING courselike %s', courselike_key)
 
         if not self.do_import_static:
             # for old-style xblock where this was actually linked to kvs
@@ -494,9 +493,9 @@ class ImportManager(object):
                     runtime=courselike.runtime,
                 )
             except Exception:
-                msg = 'failed to import module location {}'.format(leftover)
+                msg = f'failed to import module location {leftover}'
                 log.error(msg)
-                set_custom_attribute('course_import_failure', "Module Load failure: {}".format(msg))
+                set_custom_attribute('course_import_failure', f"Module Load failure: {msg}")
                 raise
 
     def run_imports(self):
@@ -601,13 +600,13 @@ class CourseImportManager(ImportManager):
         # If we are importing into a course with a different course_id and wiki_slug is equal to either of these default
         # values then remap it so that the wiki does not point to the old wiki.
         if courselike_key != course.id:
-            original_unique_wiki_slug = u'{0}.{1}.{2}'.format(
+            original_unique_wiki_slug = '{}.{}.{}'.format(
                 courselike_key.org,
                 courselike_key.course,
                 courselike_key.run
             )
             if course.wiki_slug == original_unique_wiki_slug or course.wiki_slug == courselike_key.course:
-                course.wiki_slug = u'{0}.{1}.{2}'.format(
+                course.wiki_slug = '{}.{}.{}'.format(
                     course.id.org,
                     course.id.course,
                     course.id.run,
@@ -750,7 +749,7 @@ def _update_and_import_module(
     Update all the module reference fields to the destination course id,
     then import the module into the destination course.
     """
-    logging.debug(u'processing import of module %s...', six.text_type(module.location))
+    logging.debug('processing import of module %s...', str(module.location))
 
     def _update_module_references(module, source_course_id, dest_course_id):
         """
@@ -770,7 +769,7 @@ def _update_and_import_module(
                 return reference
 
         fields = {}
-        for field_name, field in six.iteritems(module.fields):
+        for field_name, field in module.fields.items():
             if field.scope != Scope.parent and field.is_set_on(module):
                 if isinstance(field, Reference):
                     value = field.read_from(module)
@@ -786,7 +785,7 @@ def _update_and_import_module(
                     fields[field_name] = {
                         key: _convert_ref_fields_to_new_namespace(reference)
                         for key, reference
-                        in six.iteritems(reference_dict)
+                        in reference_dict.items()
                     }
                 elif field_name == 'xml_attributes':
                     value = field.read_from(module)
@@ -962,7 +961,7 @@ def _import_course_draft(
                 # Skip any OSX quarantine files, prefixed with a '._'.
                 continue
             module_path = os.path.join(rootdir, filename)
-            with io.open(module_path, 'r') as f:
+            with open(module_path, 'r') as f:
                 try:
                     xml = f.read()
 
@@ -984,7 +983,7 @@ def _import_course_draft(
 
                         index = index_in_children_list(descriptor)
                         parent_url = get_parent_url(descriptor, xml)
-                        draft_url = six.text_type(descriptor.location)
+                        draft_url = str(descriptor.location)
 
                         draft = draft_node_constructor(
                             module=descriptor, url=draft_url, parent_url=parent_url, index=index
@@ -1033,7 +1032,7 @@ def check_module_metadata_editability(module):
         print(
             ": found non-editable metadata on {url}. "
             "These metadata keys are not supported = {keys}".format(
-                url=six.text_type(module.location), keys=illegal_keys
+                url=str(module.location), keys=illegal_keys
             )
         )
 
@@ -1079,7 +1078,7 @@ def create_xml_attributes(module, xml):
     Make up for modules which don't define xml_attributes by creating them here and populating
     """
     xml_attrs = {}
-    for attr, val in six.iteritems(xml.attrib):
+    for attr, val in xml.attrib.items():
         if attr not in module.fields:
             # translate obsolete attr
             if attr == 'parent_sequential_url':
@@ -1106,7 +1105,7 @@ def validate_category_hierarchy(  # lint-amnesty, pylint: disable=missing-functi
 
     parents = []
     # get all modules of parent_category
-    for module in six.itervalues(module_store.modules[course_id]):
+    for module in module_store.modules[course_id].values():
         if module.location.block_type == parent_category:
             parents.append(module)
 
@@ -1162,7 +1161,7 @@ def validate_course_policy(module_store, course_id):
     """
     # is there a reliable way to get the module location just given the course_id?
     warn_cnt = 0
-    for module in six.itervalues(module_store.modules[course_id]):
+    for module in module_store.modules[course_id].values():
         if module.location.block_type == 'course':
             if not module._field_data.has(module, 'rerandomize'):  # lint-amnesty, pylint: disable=protected-access
                 warn_cnt += 1
@@ -1204,7 +1203,7 @@ def perform_xlint(  # lint-amnesty, pylint: disable=missing-function-docstring
         warn_cnt += _warn_cnt
 
     # first count all errors and warnings as part of the XMLModuleStore import
-    for err_log in six.itervalues(module_store._course_errors):  # pylint: disable=protected-access
+    for err_log in module_store._course_errors.values():  # pylint: disable=protected-access
         for err_log_entry in err_log.errors:
             msg = err_log_entry[0]
             if msg.startswith('ERROR:'):
@@ -1213,7 +1212,7 @@ def perform_xlint(  # lint-amnesty, pylint: disable=missing-function-docstring
                 warn_cnt += 1
 
     # then count outright all courses that failed to load at all
-    for err_log in six.itervalues(module_store.errored_courses):
+    for err_log in module_store.errored_courses.values():
         for err_log_entry in err_log.errors:
             msg = err_log_entry[0]
             print(msg)
diff --git a/common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py b/common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py
index d5c0b3011e30500a1b935241218b62ed91771792..f7ebb730a199ab12026a357d94e2bdf8b473c69a 100644
--- a/common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py
+++ b/common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py
@@ -4,7 +4,6 @@ openedx.dynamic_partition plugin.
 """
 import logging
 
-import six
 from django.conf import settings
 from django.utils.translation import ugettext_lazy as _
 
@@ -34,21 +33,21 @@ def create_enrollment_track_partition(course):
         log.warning("No 'enrollment_track' scheme registered, EnrollmentTrackUserPartition will not be created.")
         return None
 
-    used_ids = set(p.id for p in course.user_partitions)
+    used_ids = {p.id for p in course.user_partitions}
     if ENROLLMENT_TRACK_PARTITION_ID in used_ids:
         log.warning(
             "Can't add 'enrollment_track' partition, as ID {id} is assigned to {partition} in course {course}.".format(
                 id=ENROLLMENT_TRACK_PARTITION_ID,
                 partition=get_partition_from_id(course.user_partitions, ENROLLMENT_TRACK_PARTITION_ID).name,
-                course=six.text_type(course.id)
+                course=str(course.id)
             )
         )
         return None
 
     partition = enrollment_track_scheme.create_user_partition(
         id=ENROLLMENT_TRACK_PARTITION_ID,
-        name=_(u"Enrollment Track Groups"),
-        description=_(u"Partition for segmenting users by enrollment track"),
-        parameters={"course_id": six.text_type(course.id)}
+        name=_("Enrollment Track Groups"),
+        description=_("Partition for segmenting users by enrollment track"),
+        parameters={"course_id": str(course.id)}
     )
     return partition
diff --git a/common/lib/xmodule/xmodule/partitions/partitions.py b/common/lib/xmodule/xmodule/partitions/partitions.py
index 0b40ef242143ae79e04cc5b03921752a590a9425..107a797054a66d9a8532b50da55dd1e0a282fe48 100644
--- a/common/lib/xmodule/xmodule/partitions/partitions.py
+++ b/common/lib/xmodule/xmodule/partitions/partitions.py
@@ -58,7 +58,7 @@ class Group(namedtuple("Group", "id name")):
     VERSION = 1
 
     def __new__(cls, id, name):
-        return super(Group, cls).__new__(cls, int(id), name)
+        return super().__new__(cls, int(id), name)
 
     def to_json(self):
         """
@@ -88,11 +88,11 @@ class Group(namedtuple("Group", "id name")):
 
         for key in ("id", "name", "version"):
             if key not in value:
-                raise TypeError("Group dict {0} missing value key '{1}'".format(
+                raise TypeError("Group dict {} missing value key '{}'".format(
                     value, key))
 
         if value["version"] != Group.VERSION:
-            raise TypeError("Group dict {0} has unexpected version".format(
+            raise TypeError("Group dict {} has unexpected version".format(
                 value))
 
         return Group(value["id"], value["name"])
@@ -133,7 +133,7 @@ class UserPartition(namedtuple("UserPartition", "id name description groups sche
         if parameters is None:
             parameters = {}
 
-        return super(UserPartition, cls).__new__(cls, int(id), name, description, groups, scheme, parameters, active)
+        return super().__new__(cls, int(id), name, description, groups, scheme, parameters, active)
 
     @staticmethod
     def get_scheme(name):
@@ -147,7 +147,7 @@ class UserPartition(namedtuple("UserPartition", "id name description groups sche
         try:
             scheme = UserPartition.scheme_extensions[name].plugin  # lint-amnesty, pylint: disable=unsubscriptable-object
         except KeyError:
-            raise UserPartitionError("Unrecognized scheme '{0}'".format(name))  # lint-amnesty, pylint: disable=raise-missing-from
+            raise UserPartitionError(f"Unrecognized scheme '{name}'")  # lint-amnesty, pylint: disable=raise-missing-from
         scheme.name = name
         return scheme
 
@@ -184,7 +184,7 @@ class UserPartition(namedtuple("UserPartition", "id name description groups sche
 
         for key in ("id", "name", "description", "version", "groups"):
             if key not in value:
-                raise TypeError("UserPartition dict {0} missing value key '{1}'".format(value, key))
+                raise TypeError(f"UserPartition dict {value} missing value key '{key}'")
 
         if value["version"] == 1:
             # If no scheme was provided, set it to the default ('random')
@@ -195,21 +195,21 @@ class UserPartition(namedtuple("UserPartition", "id name description groups sche
         # version, we should try to read it rather than raising an exception.
         elif value["version"] >= 2:
             if "scheme" not in value:
-                raise TypeError("UserPartition dict {0} missing value key 'scheme'".format(value))
+                raise TypeError(f"UserPartition dict {value} missing value key 'scheme'")
 
             scheme_id = value["scheme"]
         else:
-            raise TypeError("UserPartition dict {0} has unexpected version".format(value))
+            raise TypeError(f"UserPartition dict {value} has unexpected version")
 
         parameters = value.get("parameters", {})
         active = value.get("active", True)
         groups = [Group.from_json(g) for g in value["groups"]]
         scheme = UserPartition.get_scheme(scheme_id)
         if not scheme:
-            raise TypeError("UserPartition dict {0} has unrecognized scheme {1}".format(value, scheme_id))
+            raise TypeError(f"UserPartition dict {value} has unrecognized scheme {scheme_id}")
 
         if getattr(scheme, 'read_only', False):
-            raise ReadOnlyUserPartitionError("UserPartition dict {0} uses scheme {1} which is read only".format(value, scheme_id))  # lint-amnesty, pylint: disable=line-too-long
+            raise ReadOnlyUserPartitionError(f"UserPartition dict {value} uses scheme {scheme_id} which is read only")  # lint-amnesty, pylint: disable=line-too-long
 
         if hasattr(scheme, "create_user_partition"):
             return scheme.create_user_partition(
diff --git a/common/lib/xmodule/xmodule/partitions/partitions_service.py b/common/lib/xmodule/xmodule/partitions/partitions_service.py
index df03e21583ac6d6f379287d9eb0732cf6208342f..3dcf6bba21edf5d2f5c4ea66913e18a41da686c0 100644
--- a/common/lib/xmodule/xmodule/partitions/partitions_service.py
+++ b/common/lib/xmodule/xmodule/partitions/partitions_service.py
@@ -81,7 +81,7 @@ def _get_dynamic_partitions(course):
     return generated_partitions
 
 
-class PartitionService(object):
+class PartitionService:
     """
     This is an XBlock service that returns information about the user partitions associated
     with a given course.
@@ -136,8 +136,8 @@ class PartitionService(object):
         user_partition = self.get_user_partition(user_partition_id)
         if user_partition is None:
             raise ValueError(
-                "Configuration problem!  No user_partition with id {0} "
-                "in course {1}".format(user_partition_id, self._course_id)
+                "Configuration problem!  No user_partition with id {} "
+                "in course {}".format(user_partition_id, self._course_id)
             )
 
         group = self.get_group(user, user_partition)
diff --git a/common/lib/xmodule/xmodule/partitions/tests/test_partitions.py b/common/lib/xmodule/xmodule/partitions/tests/test_partitions.py
index be5a1428e7f1c6464739953cdc1b0a87bfa03da0..fcbbb1a94c40350d4ee603d7bdce81a456315eaf 100644
--- a/common/lib/xmodule/xmodule/partitions/tests/test_partitions.py
+++ b/common/lib/xmodule/xmodule/partitions/tests/test_partitions.py
@@ -5,11 +5,10 @@ Test the partitions and partitions service
 
 
 from datetime import datetime
+from unittest.mock import Mock
 
 import pytest
-import six
 from django.test import TestCase
-from mock import Mock  # lint-amnesty, pylint: disable=unused-import
 from opaque_keys.edx.locator import CourseLocator
 from stevedore.extension import Extension, ExtensionManager
 
@@ -96,12 +95,12 @@ class TestGroup(TestCase):
         assert 'programmer' not in group.to_json()
 
 
-class MockUserPartitionScheme(object):
+class MockUserPartitionScheme:
     """
     Mock user partition scheme
     """
     def __init__(self, name="mock", current_group=None, **kwargs):
-        super(MockUserPartitionScheme, self).__init__(**kwargs)  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__(**kwargs)
         self.name = name
         self.current_group = current_group
 
@@ -137,7 +136,7 @@ class PartitionTestCase(TestCase):
     ENROLLMENT_TRACK_SCHEME_NAME = "enrollment_track"
 
     def setUp(self):
-        super(PartitionTestCase, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         # Set up two user partition schemes: mock and random
         self.non_random_scheme = MockUserPartitionScheme(self.TEST_SCHEME_NAME)
         self.random_scheme = MockUserPartitionScheme("random")
@@ -419,7 +418,7 @@ class MockPartitionService(PartitionService):
     Mock PartitionService for testing.
     """
     def __init__(self, course, **kwargs):
-        super(MockPartitionService, self).__init__(**kwargs)  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__(**kwargs)
         self._course = course
 
     def get_course(self):
@@ -432,7 +431,7 @@ class PartitionServiceBaseClass(PartitionTestCase):
     """
 
     def setUp(self):
-        super(PartitionServiceBaseClass, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
         ContentTypeGatingConfig.objects.create(
             enabled=True,
@@ -448,7 +447,7 @@ class PartitionServiceBaseClass(PartitionTestCase):
         # extra param to this method. Just has to be unique per user.
         user_id = abs(hash(username))
         self.user = Mock(
-            username=username, email='{}@edx.org'.format(username), is_staff=False, is_active=True, id=user_id
+            username=username, email=f'{username}@edx.org', is_staff=False, is_active=True, id=user_id
         )
         self.course.user_partitions = [self.user_partition]
 
@@ -543,7 +542,7 @@ class TestGetCourseUserPartitions(PartitionServiceBaseClass):
     """
 
     def setUp(self):
-        super(TestGetCourseUserPartitions, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         TestGetCourseUserPartitions._enable_enrollment_track_partition(True)
 
     @staticmethod
@@ -562,7 +561,7 @@ class TestGetCourseUserPartitions(PartitionServiceBaseClass):
         assert self.TEST_SCHEME_NAME == all_partitions[0].scheme.name
         enrollment_track_partition = all_partitions[1]
         assert self.ENROLLMENT_TRACK_SCHEME_NAME == enrollment_track_partition.scheme.name
-        assert six.text_type(self.course.id) == enrollment_track_partition.parameters['course_id']
+        assert str(self.course.id) == enrollment_track_partition.parameters['course_id']
         assert ENROLLMENT_TRACK_PARTITION_ID == enrollment_track_partition.id
 
     def test_enrollment_track_partition_not_added_if_conflict(self):
diff --git a/common/lib/xmodule/xmodule/progress.py b/common/lib/xmodule/xmodule/progress.py
index 60923d498c2eef38d66c73a071bfbf6281efdba7..064118f4e769a078c154530091408b6410949b74 100644
--- a/common/lib/xmodule/xmodule/progress.py
+++ b/common/lib/xmodule/xmodule/progress.py
@@ -9,7 +9,7 @@ frac() and __str__().
 import numbers
 
 
-class Progress(object):
+class Progress:  # pylint: disable=eq-without-hash
     '''Represents a progress of a/b (a out of b done)
 
     a and b must be numeric, but not necessarily integer, with
@@ -29,7 +29,7 @@ class Progress(object):
         # Want to do all checking at construction time, so explicitly check types
         if not (isinstance(a, numbers.Number) and
                 isinstance(b, numbers.Number)):
-            raise TypeError('a and b must be numbers.  Passed {0}/{1}'.format(a, b))
+            raise TypeError(f'a and b must be numbers.  Passed {a}/{b}')
 
         if a > b:
             a = b
@@ -38,7 +38,7 @@ class Progress(object):
             a = 0
 
         if b <= 0:
-            raise ValueError('fraction a/b = {0}/{1} must have b > 0'.format(a, b))
+            raise ValueError(f'fraction a/b = {a}/{b} must have b > 0')
 
         self._a = a
         self._b = b
@@ -116,8 +116,8 @@ class Progress(object):
 
         '''
         (a, b) = self.frac()
-        display = lambda n: '{:.2f}'.format(n).rstrip('0').rstrip('.')
-        return "{0}/{1}".format(display(a), display(b))
+        display = lambda n: f'{n:.2f}'.rstrip('0').rstrip('.')
+        return "{}/{}".format(display(a), display(b))
 
     @staticmethod
     def add_counts(a, b):
diff --git a/common/lib/xmodule/xmodule/randomize_module.py b/common/lib/xmodule/xmodule/randomize_module.py
index 7067b5c13c34fedd267293c597cadf8291d1cdb3..2079c7246fc098f35f65c7bce8d56ffb26c30192 100644
--- a/common/lib/xmodule/xmodule/randomize_module.py
+++ b/common/lib/xmodule/xmodule/randomize_module.py
@@ -102,7 +102,7 @@ class RandomizeBlock(
         """
         if self.child is None:
             # raise error instead?  In fact, could complain on descriptor load...
-            return Fragment(content=u"<div>Nothing to randomize between</div>")
+            return Fragment(content="<div>Nothing to randomize between</div>")
 
         return self.child.render(STUDENT_VIEW, context)
 
diff --git a/common/lib/xmodule/xmodule/raw_module.py b/common/lib/xmodule/xmodule/raw_module.py
index 86ec4a58d803b58a2cf2cee2d2cdc0622aa9a1f5..a07f51e658a3251c7800f1499b914ea7c2433512 100644
--- a/common/lib/xmodule/xmodule/raw_module.py
+++ b/common/lib/xmodule/xmodule/raw_module.py
@@ -14,7 +14,7 @@ log = logging.getLogger(__name__)
 PRE_TAG_REGEX = re.compile(r'<pre\b[^>]*>(?:(?=([^<]+))\1|<(?!pre\b[^>]*>))*?</pre>')
 
 
-class RawMixin(object):
+class RawMixin:
     """
     Common code between RawDescriptor and XBlocks converted from XModules.
     """
@@ -68,8 +68,8 @@ class RawMixin(object):
             lines = self.data.split('\n')
             line, offset = err.position
             msg = (
-                u"Unable to create xml for module {loc}. "
-                u"Context: '{context}'"
+                "Unable to create xml for module {loc}. "
+                "Context: '{context}'"
             ).format(
                 context=lines[line - 1][offset - 40:offset + 40],
                 loc=self.location,
@@ -92,9 +92,9 @@ class RawMixin(object):
             node.remove(child)
         # Get attributes, if any, via normal parse_xml.
         try:
-            block = super(RawMixin, cls).parse_xml_new_runtime(node, runtime, keys)
+            block = super().parse_xml_new_runtime(node, runtime, keys)
         except AttributeError:
-            block = super(RawMixin, cls).parse_xml(node, runtime, keys, id_generator=None)
+            block = super().parse_xml(node, runtime, keys, id_generator=None)
         block.data = data_field_value
         return block
 
@@ -107,7 +107,7 @@ class RawDescriptor(RawMixin, XmlDescriptor, XMLEditingDescriptor):
     pass  # lint-amnesty, pylint: disable=unnecessary-pass
 
 
-class EmptyDataRawMixin(object):
+class EmptyDataRawMixin:
     """
     Common code between EmptyDataRawDescriptor and XBlocks converted from XModules.
     """
diff --git a/common/lib/xmodule/xmodule/seq_module.py b/common/lib/xmodule/xmodule/seq_module.py
index 69fa86b09b911bda4accc8338230b6885a5e6e78..96694aea9db23780b7e643d1f0ee2ad670a5f18c 100644
--- a/common/lib/xmodule/xmodule/seq_module.py
+++ b/common/lib/xmodule/xmodule/seq_module.py
@@ -11,12 +11,10 @@ import logging
 from datetime import datetime
 from functools import reduce
 
-import six
 from lxml import etree
 from opaque_keys.edx.keys import UsageKey
 from pkg_resources import resource_string
 from pytz import UTC
-from six import text_type
 from web_fragments.fragment import Fragment
 from xblock.completable import XBlockCompletionMode
 from xblock.core import XBlock
@@ -61,12 +59,12 @@ _ = lambda text: text
 
 TIMED_EXAM_GATING_WAFFLE_FLAG = LegacyWaffleFlag(
     waffle_namespace="xmodule",
-    flag_name=u'rev_1377_rollout',
+    flag_name='rev_1377_rollout',
     module_name=__name__,
 )
 
 
-class SequenceFields(object):  # lint-amnesty, pylint: disable=missing-class-docstring
+class SequenceFields:  # lint-amnesty, pylint: disable=missing-class-docstring
     has_children = True
     completion_mode = XBlockCompletionMode.AGGREGATOR
 
@@ -138,7 +136,7 @@ class SequenceMixin(SequenceFields):
         return xblock_body
 
 
-class ProctoringFields(object):
+class ProctoringFields:
     """
     Fields that are specific to Proctored or Timed Exams
     """
@@ -315,7 +313,7 @@ class SequenceBlock(
         if dispatch == 'goto_position':
             # set position to default value if either 'position' argument not
             # found in request or it is a non-positive integer
-            position = data.get('position', u'1')
+            position = data.get('position', '1')
             if position.isdigit() and int(position) > 0:
                 self.position = int(position)
             else:
@@ -516,7 +514,7 @@ class SequenceBlock(
         params = {
             'items': items,
             'element_id': self.location.html_id(),
-            'item_id': text_type(self.location),
+            'item_id': str(self.location),
             'is_time_limited': self.is_time_limited,
             'position': self.position,
             'tag': self.location.block_type,
@@ -742,7 +740,7 @@ class SequenceBlock(
                 'content': content,
                 'page_title': getattr(item, 'tooltip_title', ''),
                 'type': item_type,
-                'id': text_type(usage_id),
+                'id': str(usage_id),
                 'bookmarked': is_bookmarked,
                 'path': " > ".join(display_names + [item.display_name_with_default]),
                 'graded': item.graded,
@@ -783,7 +781,7 @@ class SequenceBlock(
         """
         if not newrelic:
             return
-        newrelic.agent.add_custom_parameter('seq.block_id', six.text_type(self.location))
+        newrelic.agent.add_custom_parameter('seq.block_id', str(self.location))
         newrelic.agent.add_custom_parameter('seq.display_name', self.display_name or '')
         newrelic.agent.add_custom_parameter('seq.position', self.position)
         newrelic.agent.add_custom_parameter('seq.is_time_limited', self.is_time_limited)
@@ -808,7 +806,7 @@ class SequenceBlock(
         # Count of all modules by block_type (e.g. "video": 2, "discussion": 4)
         block_counts = collections.Counter(usage_key.block_type for usage_key in all_item_keys)
         for block_type, count in block_counts.items():
-            newrelic.agent.add_custom_parameter('seq.block_counts.{}'.format(block_type), count)
+            newrelic.agent.add_custom_parameter(f'seq.block_counts.{block_type}', count)
 
     def _capture_current_unit_metrics(self, display_items):
         """
@@ -822,7 +820,7 @@ class SequenceBlock(
         if 1 <= self.position <= len(display_items):
             # Basic info about the Unit...
             current = display_items[self.position - 1]
-            newrelic.agent.add_custom_parameter('seq.current.block_id', six.text_type(current.location))
+            newrelic.agent.add_custom_parameter('seq.current.block_id', str(current.location))
             newrelic.agent.add_custom_parameter('seq.current.display_name', current.display_name or '')
 
             # Examining all items inside the Unit (or split_test, conditional, etc.)
@@ -830,7 +828,7 @@ class SequenceBlock(
             newrelic.agent.add_custom_parameter('seq.current.num_items', len(child_locs))
             curr_block_counts = collections.Counter(usage_key.block_type for usage_key in child_locs)
             for block_type, count in curr_block_counts.items():
-                newrelic.agent.add_custom_parameter('seq.current.block_counts.{}'.format(block_type), count)
+                newrelic.agent.add_custom_parameter(f'seq.current.block_counts.{block_type}', count)
 
     def _time_limited_student_view(self):
         """
@@ -906,8 +904,8 @@ class SequenceBlock(
         return view_html
 
     def get_icon_class(self):
-        child_classes = set(child.get_icon_class()
-                            for child in self.get_children())
+        child_classes = {child.get_icon_class()
+                         for child in self.get_children()}
         new_class = 'other'
         for c in class_priority:
             if c in child_classes:
@@ -930,7 +928,7 @@ class SequenceBlock(
         return non_editable_fields
 
 
-class HighlightsFields(object):
+class HighlightsFields:
     """Only Sections have summaries now, but we may expand that later."""
     highlights = List(
         help=_("A list summarizing what students should look forward to in this section."),
diff --git a/common/lib/xmodule/xmodule/services.py b/common/lib/xmodule/xmodule/services.py
index c8b194a951cae0f84934183cbec148d1be4e02b2..f829862f55d5dfb8b4e4e5347f8bab901e2c035f 100644
--- a/common/lib/xmodule/xmodule/services.py
+++ b/common/lib/xmodule/xmodule/services.py
@@ -10,7 +10,7 @@ from django.conf import settings
 from xmodule.modulestore.django import modulestore
 
 
-class SettingsService(object):
+class SettingsService:
     """
     Allows server-wide configuration of XBlocks on a per-type basis
 
@@ -61,7 +61,7 @@ class SettingsService(object):
     def get_settings_bucket(self, block, default=None):
         """ Gets xblock settings dictionary from settings. """
         if not block:
-            raise ValueError("Expected XBlock instance, got {0} of type {1}".format(block, type(block)))
+            raise ValueError("Expected XBlock instance, got {} of type {}".format(block, type(block)))
 
         actual_default = default if default is not None else {}
         xblock_settings_bucket = getattr(block, self.xblock_settings_bucket_selector, block.unmixed_class.__name__)
@@ -71,7 +71,7 @@ class SettingsService(object):
 
 # TODO: ConfigurationService and its usage will be removed as a part of EDUCATOR-121
 # reference: https://openedx.atlassian.net/browse/EDUCATOR-121
-class ConfigurationService(object):
+class ConfigurationService:
     """
     An XBlock service to talk with the Configuration Models. This service should provide
     a pathway to Configuration Model which is designed to configure the corresponding XBlock.
@@ -89,7 +89,7 @@ class ConfigurationService(object):
         """
         if not (inspect.isclass(configuration_model) and issubclass(configuration_model, ConfigurationModel)):
             raise ValueError(
-                "Expected ConfigurationModel got {0} of type {1}".format(
+                "Expected ConfigurationModel got {} of type {}".format(
                     configuration_model,
                     type(configuration_model)
                 )
@@ -98,7 +98,7 @@ class ConfigurationService(object):
         self.configuration = configuration_model
 
 
-class TeamsConfigurationService(object):
+class TeamsConfigurationService:
     """
     An XBlock service that returns the teams_configuration object for a course.
     """
diff --git a/common/lib/xmodule/xmodule/split_test_module.py b/common/lib/xmodule/xmodule/split_test_module.py
index d1857076eab622a75fb363b28871753f2f24a7bb..0f9f7ec33782a1f7dee251eac86da2accb6a8079 100644
--- a/common/lib/xmodule/xmodule/split_test_module.py
+++ b/common/lib/xmodule/xmodule/split_test_module.py
@@ -10,11 +10,9 @@ from functools import reduce
 from operator import itemgetter
 from uuid import uuid4
 
-import six
 from django.utils.functional import cached_property
 from lxml import etree
 from pkg_resources import resource_string
-from six import text_type
 from web_fragments.fragment import Fragment
 from webob import Response
 from xblock.core import XBlock
@@ -43,7 +41,7 @@ log = logging.getLogger('edx.' + __name__)
 #  `django.utils.translation.ugettext_noop` because Django cannot be imported in this file
 _ = lambda text: text
 
-DEFAULT_GROUP_NAME = _(u'Group ID {group_id}')
+DEFAULT_GROUP_NAME = _('Group ID {group_id}')
 
 
 class UserPartitionValues(threading.local):
@@ -75,7 +73,7 @@ class UserPartitionValues(threading.local):
 user_partition_values = UserPartitionValues()
 
 
-class SplitTestFields(object):
+class SplitTestFields:
     """Fields needed for split test module"""
     has_children = True
 
@@ -284,8 +282,8 @@ class SplitTestBlock(
                 group_name = child.display_name
                 updated_group_id = [g_id for g_id, loc in self.group_id_to_child.items() if loc == child_location][0]
                 inactive_contents.append({
-                    'group_name': _(u'{group_name} (inactive)').format(group_name=group_name),
-                    'id': text_type(child.location),
+                    'group_name': _('{group_name} (inactive)').format(group_name=group_name),
+                    'id': str(child.location),
                     'content': rendered_child.content,
                     'group_id': updated_group_id,
                 })
@@ -293,7 +291,7 @@ class SplitTestBlock(
 
             active_contents.append({
                 'group_name': group_name,
-                'id': text_type(child.location),
+                'id': str(child.location),
                 'content': rendered_child.content,
                 'group_id': updated_group_id,
             })
@@ -382,7 +380,7 @@ class SplitTestBlock(
         """
         if self.child is None:
             # raise error instead?  In fact, could complain on descriptor load...
-            return Fragment(content=u"<div>Nothing here.  Move along.</div>")
+            return Fragment(content="<div>Nothing here.  Move along.</div>")
 
         if self.system.user_is_staff:
             return self._staff_view(context)
@@ -404,11 +402,11 @@ class SplitTestBlock(
         """
         # TODO: use publish instead, when publish is wired to the tracking logs
         try:
-            child_id = text_type(self.child.scope_ids.usage_id)
+            child_id = str(self.child.scope_ids.usage_id)
         except Exception:
             log.info(
                 "Can't get usage_id of Nonetype object in course {course_key}".format(
-                    course_key=six.text_type(self.location.course_key)
+                    course_key=str(self.location.course_key)
                 )
             )
             raise
@@ -432,7 +430,7 @@ class SplitTestBlock(
         user_partition = self.get_selected_partition()
         if user_partition:
             for group in user_partition.groups:
-                group_id = six.text_type(group.id)
+                group_id = str(group.id)
                 child_location = self.group_id_to_child.get(group_id, None)
                 if child_location == vertical.location:
                     return (group.name, group.id)
@@ -447,7 +445,7 @@ class SplitTestBlock(
         renderable_groups = {}
         # json.dumps doesn't know how to handle Location objects
         for group in self.group_id_to_child:
-            renderable_groups[group] = text_type(self.group_id_to_child[group])
+            renderable_groups[group] = str(self.group_id_to_child[group])
         xml_object.set('group_id_to_child', json.dumps(renderable_groups))
         xml_object.set('user_partition_id', str(self.user_partition_id))
         for child in self.get_children():
@@ -577,7 +575,7 @@ class SplitTestBlock(
         # Compute the active children in the order specified by the user partition
         active_children = []
         for group in user_partition.groups:
-            group_id = six.text_type(group.id)
+            group_id = str(group.id)
             child_location = self.group_id_to_child.get(group_id, None)
             child = get_child_descriptor(child_location)
             if child:
@@ -626,9 +624,9 @@ class SplitTestBlock(
             split_validation.add(
                 StudioValidationMessage(
                     StudioValidationMessage.NOT_CONFIGURED,
-                    _(u"The experiment is not associated with a group configuration."),
+                    _("The experiment is not associated with a group configuration."),
                     action_class='edit-button',
-                    action_label=_(u"Select a Group Configuration")
+                    action_label=_("Select a Group Configuration")
                 )
             )
         else:
@@ -637,7 +635,7 @@ class SplitTestBlock(
                 split_validation.add(
                     StudioValidationMessage(
                         StudioValidationMessage.ERROR,
-                        _(u"The experiment uses a deleted group configuration. Select a valid group configuration or delete this experiment.")  # lint-amnesty, pylint: disable=line-too-long
+                        _("The experiment uses a deleted group configuration. Select a valid group configuration or delete this experiment.")  # lint-amnesty, pylint: disable=line-too-long
                     )
                 )
             else:
@@ -647,8 +645,8 @@ class SplitTestBlock(
                     split_validation.add(
                         StudioValidationMessage(
                             StudioValidationMessage.ERROR,
-                            _(u"The experiment uses a group configuration that is not supported for experiments. "
-                              u"Select a valid group configuration or delete this experiment.")
+                            _("The experiment uses a group configuration that is not supported for experiments. "
+                              "Select a valid group configuration or delete this experiment.")
                         )
                     )
                 else:
@@ -657,17 +655,17 @@ class SplitTestBlock(
                         split_validation.add(
                             StudioValidationMessage(
                                 StudioValidationMessage.ERROR,
-                                _(u"The experiment does not contain all of the groups in the configuration."),
+                                _("The experiment does not contain all of the groups in the configuration."),
                                 action_runtime_event='add-missing-groups',
-                                action_label=_(u"Add Missing Groups")
+                                action_label=_("Add Missing Groups")
                             )
                         )
                     if len(inactive_children) > 0:
                         split_validation.add(
                             StudioValidationMessage(
                                 StudioValidationMessage.WARNING,
-                                _(u"The experiment has an inactive group. "
-                                  u"Move content into active groups, then delete the inactive group.")
+                                _("The experiment has an inactive group. "
+                                  "Move content into active groups, then delete the inactive group.")
                             )
                         )
         return split_validation
@@ -685,7 +683,7 @@ class SplitTestBlock(
             has_error = any(message.type == StudioValidationMessage.ERROR for message in validation.messages)
             return StudioValidationMessage(
                 StudioValidationMessage.ERROR if has_error else StudioValidationMessage.WARNING,
-                _(u"This content experiment has issues that affect content visibility.")
+                _("This content experiment has issues that affect content visibility.")
             )
         return None
 
@@ -700,7 +698,7 @@ class SplitTestBlock(
 
         changed = False
         for group in user_partition.groups:
-            str_group_id = six.text_type(group.id)
+            str_group_id = str(group.id)
             if str_group_id not in self.group_id_to_child:
                 user_id = self.runtime.service(self, 'user').get_current_user().opt_attrs['edx-platform.user_id']
                 self._create_vertical_for_group(group, user_id)
@@ -722,7 +720,7 @@ class SplitTestBlock(
             user_partition = self.get_selected_partition()
             if user_partition:
                 group_configuration_url = "{url}#{configuration_id}".format(
-                    url='/group_configurations/' + six.text_type(self.location.course_key),
+                    url='/group_configurations/' + str(self.location.course_key),
                     configuration_id=str(user_partition.id)
                 )
 
@@ -751,4 +749,4 @@ class SplitTestBlock(
             runtime=self.system,
         )
         self.children.append(dest_usage_key)  # pylint: disable=no-member
-        self.group_id_to_child[six.text_type(group.id)] = dest_usage_key
+        self.group_id_to_child[str(group.id)] = dest_usage_key
diff --git a/common/lib/xmodule/xmodule/static_content.py b/common/lib/xmodule/xmodule/static_content.py
index 58e03bd05ac5d0f3e87512430c6d34cdf53937e0..bf48f37883a9d03d8ed2140ea7ae1d602f2dfb3f 100755
--- a/common/lib/xmodule/xmodule/static_content.py
+++ b/common/lib/xmodule/xmodule/static_content.py
@@ -16,7 +16,6 @@ from collections import defaultdict
 from pkg_resources import resource_string
 
 import django
-import six
 from docopt import docopt
 from path import Path as path
 
@@ -179,7 +178,7 @@ def _write_styles(selector, output_root, classes, css_attribute):
         module_styles_lines.append("""{selector}.xmodule_{class_} {{""".format(
             class_=class_, selector=selector
         ))
-        module_styles_lines.extend('  @import "{0}";'.format(name) for name in fragment_names)
+        module_styles_lines.extend(f'  @import "{name}";' for name in fragment_names)
         module_styles_lines.append('}')
 
     contents['_module-styles.scss'] = '\n'.join(module_styles_lines)
@@ -236,7 +235,7 @@ def _write_files(output_root, contents, generated_suffix_map=None):
         will be ignored
     """
     _ensure_dir(output_root)
-    to_delete = set(file.basename() for file in output_root.files()) - set(contents.keys())
+    to_delete = {file.basename() for file in output_root.files()} - set(contents.keys())
 
     if generated_suffix_map:
         for output_file in contents.keys():
@@ -247,7 +246,7 @@ def _write_files(output_root, contents, generated_suffix_map=None):
     for extra_file in to_delete:
         (output_root / extra_file).remove_p()
 
-    for filename, file_content in six.iteritems(contents):
+    for filename, file_content in contents.items():
         output_file = output_root / filename
 
         not_file = not output_file.isfile()
@@ -255,7 +254,7 @@ def _write_files(output_root, contents, generated_suffix_map=None):
         # Sometimes content is already unicode and sometimes it's not
         # so we add this conditional here to make sure that below we're
         # always working with streams of bytes.
-        if not isinstance(file_content, six.binary_type):
+        if not isinstance(file_content, bytes):
             file_content = file_content.encode('utf-8')
 
         # not_file is included to short-circuit this check, because
@@ -280,7 +279,7 @@ def write_webpack(output_file, module_files, descriptor_files):
         'entry': {}
     }
     for (owner, files) in list(module_files.items()) + list(descriptor_files.items()):
-        unique_files = sorted(set('./{}'.format(file) for file in files))
+        unique_files = sorted({f'./{file}' for file in files})
         if len(unique_files) == 1:
             unique_files = unique_files[0]
         config['entry'][owner] = unique_files
@@ -289,7 +288,7 @@ def write_webpack(output_file, module_files, descriptor_files):
 
     with output_file.open('w') as outfile:
         outfile.write(
-            textwrap.dedent(u"""\
+            textwrap.dedent("""\
                 module.exports = {config_json};
             """).format(
                 config_json=json.dumps(
diff --git a/common/lib/xmodule/xmodule/stringify.py b/common/lib/xmodule/xmodule/stringify.py
index 0ff52846d18e334071a5abc67c452ff370ec8860..c97af7232338cdb90d97ed41d29405599b079298 100644
--- a/common/lib/xmodule/xmodule/stringify.py
+++ b/common/lib/xmodule/xmodule/stringify.py
@@ -1,5 +1,4 @@
 # lint-amnesty, pylint: disable=missing-module-docstring
-# -*- coding: utf-8 -*-
 
 from lxml import etree
 
@@ -28,4 +27,4 @@ def stringify_children(node):
         parts.append(etree.tostring(c, with_tail=True, encoding='unicode'))
 
     # filter removes possible Nones in texts and tails
-    return u''.join([part for part in parts if part])
+    return ''.join([part for part in parts if part])
diff --git a/common/lib/xmodule/xmodule/studio_editable.py b/common/lib/xmodule/xmodule/studio_editable.py
index 241953935cab7e9d6b3438110888d15992385322..8352c781d14e206155dba973e81a1db27d4ac8d3 100644
--- a/common/lib/xmodule/xmodule/studio_editable.py
+++ b/common/lib/xmodule/xmodule/studio_editable.py
@@ -1,13 +1,10 @@
 """
 Mixin to support editing in Studio.
 """
-
-
-import six
 from xmodule.x_module import AUTHOR_VIEW, STUDENT_VIEW, module_attr
 
 
-class StudioEditableBlock(object):
+class StudioEditableBlock:
     """
     Helper methods for supporting Studio editing of XBlocks.
 
@@ -30,7 +27,7 @@ class StudioEditableBlock(object):
             fragment.add_fragment_resources(rendered_child)
 
             contents.append({
-                'id': six.text_type(child.location),
+                'id': str(child.location),
                 'content': rendered_child.content
             })
 
@@ -52,7 +49,7 @@ class StudioEditableBlock(object):
 StudioEditableModule = StudioEditableBlock
 
 
-class StudioEditableDescriptor(object):
+class StudioEditableDescriptor:
     """
     Helper mixin for supporting Studio editing of xmodules.
 
diff --git a/common/lib/xmodule/xmodule/tabs.py b/common/lib/xmodule/xmodule/tabs.py
index 5e1a7747846cbc33dfd150444f9775cba8c36089..40ed7863da8781af9a7c10e8040948326ea317c9 100644
--- a/common/lib/xmodule/xmodule/tabs.py
+++ b/common/lib/xmodule/xmodule/tabs.py
@@ -6,9 +6,7 @@ Implement CourseTab
 import logging
 from abc import ABCMeta
 
-import six
 from django.core.files.storage import get_storage_class
-from six import text_type
 from xblock.fields import List
 
 from edx_django_utils.plugins import PluginError
@@ -23,7 +21,7 @@ _ = lambda text: text
 READ_ONLY_COURSE_TAB_ATTRIBUTES = ['type']
 
 
-class CourseTab(six.with_metaclass(ABCMeta, object)):
+class CourseTab(metaclass=ABCMeta):
     """
     The Course Tab class is a data abstraction for all tabs (i.e., course navigation links) within a course.
     It is an abstract class - to be inherited by various tab types.
@@ -85,7 +83,7 @@ class CourseTab(six.with_metaclass(ABCMeta, object)):
         Args:
             tab_dict (dict) - a dictionary of parameters used to build the tab.
         """
-        super(CourseTab, self).__init__()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__()
         self.name = tab_dict.get('name', self.title)
         self.tab_id = tab_dict.get('tab_id', getattr(self, 'tab_id', self.type))
         self.course_staff_only = tab_dict.get('course_staff_only', False)
@@ -129,7 +127,7 @@ class CourseTab(six.with_metaclass(ABCMeta, object)):
         if hasattr(self, key):
             return getattr(self, key, None)
         else:
-            raise KeyError('Key {0} not present in tab {1}'.format(key, self.to_json()))
+            raise KeyError(f'Key {key} not present in tab {self.to_json()}')
 
     def __setitem__(self, key, value):
         """
@@ -141,7 +139,7 @@ class CourseTab(six.with_metaclass(ABCMeta, object)):
         if hasattr(self, key) and key not in READ_ONLY_COURSE_TAB_ATTRIBUTES:
             setattr(self, key, value)
         else:
-            raise KeyError('Key {0} cannot be set in tab {1}'.format(key, self.to_json()))
+            raise KeyError(f'Key {key} cannot be set in tab {self.to_json()}')
 
     def __eq__(self, other):
         """
@@ -245,14 +243,14 @@ class CourseTab(six.with_metaclass(ABCMeta, object)):
         return tab_type(tab_dict=tab_dict)
 
 
-class TabFragmentViewMixin(object):
+class TabFragmentViewMixin:
     """
     A mixin for tabs that render themselves as web fragments.
     """
     fragment_view_name = None
 
     def __init__(self, tab_dict):
-        super(TabFragmentViewMixin, self).__init__(tab_dict)  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__(tab_dict)
         self._fragment_view = None
 
     @property
@@ -261,12 +259,12 @@ class TabFragmentViewMixin(object):
 
         # If a view_name is specified, then use the default link function
         if self.view_name:
-            return super(TabFragmentViewMixin, self).link_func  # lint-amnesty, pylint: disable=super-with-arguments
+            return super().link_func
 
         # If not, then use the generic course tab URL
         def link_func(course, reverse_func):
             """ Returns a function that returns the course tab's URL. """
-            return reverse_func("course_tab_view", args=[text_type(course.id), self.type])
+            return reverse_func("course_tab_view", args=[str(course.id), self.type])
 
         return link_func
 
@@ -290,7 +288,7 @@ class TabFragmentViewMixin(object):
         """
         Renders this tab to a web fragment.
         """
-        return self.fragment_view.render_to_fragment(request, course_id=six.text_type(course.id), **kwargs)
+        return self.fragment_view.render_to_fragment(request, course_id=str(course.id), **kwargs)
 
     def __hash__(self):
         """ Return a hash representation of Tab Object. """
@@ -308,7 +306,7 @@ class StaticTab(CourseTab):
     def __init__(self, tab_dict=None, name=None, url_slug=None):
         def link_func(course, reverse_func):
             """ Returns a function that returns the static tab's URL. """
-            return reverse_func(self.type, args=[text_type(course.id), self.url_slug])
+            return reverse_func(self.type, args=[str(course.id), self.url_slug])
 
         self.url_slug = tab_dict.get('url_slug') if tab_dict else url_slug
 
@@ -319,9 +317,9 @@ class StaticTab(CourseTab):
             tab_dict['name'] = name
 
         tab_dict['link_func'] = link_func
-        tab_dict['tab_id'] = 'static_tab_{0}'.format(self.url_slug)
+        tab_dict['tab_id'] = f'static_tab_{self.url_slug}'
 
-        super(StaticTab, self).__init__(tab_dict)  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__(tab_dict)
 
     @classmethod
     def is_enabled(cls, course, user=None):
@@ -335,29 +333,29 @@ class StaticTab(CourseTab):
         """
         Ensures that the specified tab_dict is valid.
         """
-        return (super(StaticTab, cls).validate(tab_dict, raise_error)
+        return (super().validate(tab_dict, raise_error)
                 and key_checker(['name', 'url_slug'])(tab_dict, raise_error))
 
     def __getitem__(self, key):
         if key == 'url_slug':
             return self.url_slug
         else:
-            return super(StaticTab, self).__getitem__(key)  # lint-amnesty, pylint: disable=super-with-arguments
+            return super().__getitem__(key)
 
     def __setitem__(self, key, value):
         if key == 'url_slug':
             self.url_slug = value
         else:
-            super(StaticTab, self).__setitem__(key, value)  # lint-amnesty, pylint: disable=super-with-arguments
+            super().__setitem__(key, value)
 
     def to_json(self):
         """ Return a dictionary representation of this tab. """
-        to_json_val = super(StaticTab, self).to_json()  # lint-amnesty, pylint: disable=super-with-arguments
+        to_json_val = super().to_json()
         to_json_val.update({'url_slug': self.url_slug})
         return to_json_val
 
     def __eq__(self, other):
-        if not super(StaticTab, self).__eq__(other):  # lint-amnesty, pylint: disable=super-with-arguments
+        if not super().__eq__(other):
             return False
         return self.url_slug == other.get('url_slug')
 
@@ -461,8 +459,7 @@ class CourseTabList(List):
                     # If rendering inline that add each item in the collection,
                     # else just show the tab itself as long as it is not empty.
                     if inline_collections:
-                        for item in tab.items(course):
-                            yield item
+                        yield from tab.items(course)
                     elif len(list(tab.items(course))) > 0:
                         yield tab
                 else:
@@ -496,15 +493,15 @@ class CourseTabList(List):
             return
 
         if len(tabs) < 2:
-            raise InvalidTabsException("Expected at least two tabs.  tabs: '{0}'".format(tabs))
+            raise InvalidTabsException(f"Expected at least two tabs.  tabs: '{tabs}'")
 
         if tabs[0].get('type') != 'course_info':
             raise InvalidTabsException(
-                "Expected first tab to have type 'course_info'.  tabs: '{0}'".format(tabs))
+                f"Expected first tab to have type 'course_info'.  tabs: '{tabs}'")
 
         if tabs[1].get('type') != 'courseware':
             raise InvalidTabsException(
-                "Expected second tab to have type 'courseware'.  tabs: '{0}'".format(tabs))
+                f"Expected second tab to have type 'courseware'.  tabs: '{tabs}'")
 
         # the following tabs should appear only once
         # TODO: don't import openedx capabilities from common
@@ -574,7 +571,7 @@ def key_checker(expected_keys):
             return True
         if raise_error:  # lint-amnesty, pylint: disable=no-else-raise
             raise InvalidTabsException(
-                "Expected keys '{0}' are not present in the given dict: {1}".format(expected_keys, actual_dict)
+                f"Expected keys '{expected_keys}' are not present in the given dict: {actual_dict}"
             )
         else:
             return False
@@ -620,7 +617,7 @@ def course_reverse_func_from_name_func(reverse_name_func):
     """
     return lambda course, reverse_url_func: reverse_url_func(
         reverse_name_func(course),
-        args=[text_type(course.id)]
+        args=[str(course.id)]
     )
 
 
diff --git a/common/lib/xmodule/xmodule/template_module.py b/common/lib/xmodule/xmodule/template_module.py
index a94cf457fa29e7262707e2da18a4d5b704e99508..8a5211353e207dba7e580b86b948387971fdd5be 100644
--- a/common/lib/xmodule/xmodule/template_module.py
+++ b/common/lib/xmodule/xmodule/template_module.py
@@ -93,7 +93,7 @@ class CustomTagBlock(
                 template_name = child_impl.text
             else:
                 # TODO (vshnayder): better exception type
-                raise Exception("Could not find impl attribute in customtag {0}"
+                raise Exception("Could not find impl attribute in customtag {}"
                                 .format(self.location))
 
         params = dict(list(xmltree.items()))
diff --git a/common/lib/xmodule/xmodule/tests/__init__.py b/common/lib/xmodule/xmodule/tests/__init__.py
index f8b531aa52e8aaf76ac4d78320e69a25b1c6c483..5f3639a7bedaef9cba11d54ce918a1940e83b2af 100644
--- a/common/lib/xmodule/xmodule/tests/__init__.py
+++ b/common/lib/xmodule/xmodule/tests/__init__.py
@@ -17,14 +17,12 @@ import traceback
 import unittest
 from contextlib import contextmanager
 from functools import wraps
+from unittest.mock import Mock
 
-import six
 from django.test import TestCase
 from django.utils.encoding import python_2_unicode_compatible
-from mock import Mock
 from opaque_keys.edx.keys import CourseKey
 from path import Path as path
-from six import text_type
 from xblock.core import XBlock
 from xblock.field_data import DictFieldData
 from xblock.fields import Reference, ReferenceList, ReferenceValueDict, ScopeIds
@@ -53,11 +51,11 @@ class TestModuleSystem(ModuleSystem):  # pylint: disable=abstract-method
         kwargs.setdefault('id_reader', id_manager)
         kwargs.setdefault('id_generator', id_manager)
         kwargs.setdefault('services', {}).setdefault('field-data', DictFieldData({}))
-        super(TestModuleSystem, self).__init__(**kwargs)  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__(**kwargs)
 
     def handler_url(self, block, handler, suffix='', query='', thirdparty=False):  # lint-amnesty, pylint: disable=arguments-differ
         return '{usage_id}/{handler}{suffix}?{query}'.format(
-            usage_id=six.text_type(block.scope_ids.usage_id),
+            usage_id=str(block.scope_ids.usage_id),
             handler=handler,
             suffix=suffix,
             query=query,
@@ -65,7 +63,7 @@ class TestModuleSystem(ModuleSystem):  # pylint: disable=abstract-method
 
     def local_resource_url(self, block, uri):
         return 'resource/{usage_id}/{uri}'.format(
-            usage_id=six.text_type(block.scope_ids.usage_id),
+            usage_id=str(block.scope_ids.usage_id),
             uri=uri,
         )
 
@@ -84,7 +82,7 @@ class TestModuleSystem(ModuleSystem):  # pylint: disable=abstract-method
         if hasattr(self, '_view_name'):
             orig_view_name = self._view_name
         self._view_name = None
-        rt_repr = super(TestModuleSystem, self).__repr__()  # lint-amnesty, pylint: disable=super-with-arguments
+        rt_repr = super().__repr__()
         self._view_name = orig_view_name
         return rt_repr
 
@@ -202,12 +200,12 @@ def map_references(value, field, actual_course_key):
     if isinstance(field, ReferenceList):
         return [sub.map_into_course(actual_course_key) for sub in value]
     if isinstance(field, ReferenceValueDict):
-        return {key: ele.map_into_course(actual_course_key) for key, ele in six.iteritems(value)}
+        return {key: ele.map_into_course(actual_course_key) for key, ele in value.items()}
     return value
 
 
 @python_2_unicode_compatible
-class LazyFormat(object):
+class LazyFormat:
     """
     An stringy object that delays formatting until it's put into a string context.
     """
@@ -225,13 +223,13 @@ class LazyFormat(object):
         return self._message
 
     def __repr__(self):
-        return six.text_type(self)
+        return str(self)
 
     def __len__(self):
-        return len(six.text_type(self))
+        return len(str(self))
 
     def __getitem__(self, index):
-        return six.text_type(self)[index]
+        return str(self)[index]
 
 
 class CourseComparisonTest(TestCase):
@@ -240,7 +238,7 @@ class CourseComparisonTest(TestCase):
     """
 
     def setUp(self):
-        super(CourseComparisonTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.field_exclusions = set()
         self.ignored_asset_keys = set()
 
@@ -283,8 +281,8 @@ class CourseComparisonTest(TestCase):
             expected = [extract_key(key) for key in expected]
             actual = [extract_key(key) for key in actual]
         elif isinstance(reference_field, ReferenceValueDict):
-            expected = {key: extract_key(val) for (key, val) in six.iteritems(expected)}
-            actual = {key: extract_key(val) for (key, val) in six.iteritems(actual)}
+            expected = {key: extract_key(val) for (key, val) in expected.items()}
+            actual = {key: extract_key(val) for (key, val) in actual.items()}
         assert expected == actual,\
             LazyFormat("Field {} doesn't match between usages {} and {}: {!r} != {!r}",
                        reference_field.name,
@@ -365,8 +363,7 @@ class CourseComparisonTest(TestCase):
         }
         # Split Mongo and Old-Mongo disagree about what the block_id of courses is, so skip those in
         # this comparison
-        six.assertCountEqual(
-            self,
+        self.assertCountEqual(
             [map_key(item.location) for item in expected_items if item.scope_ids.block_type != 'course'],
             [key for key in actual_item_map.keys() if key[0] != 'course'],
         )
@@ -387,7 +384,7 @@ class CourseComparisonTest(TestCase):
                 continue
             # compare fields
             assert expected_item.fields == actual_item.fields
-            for field_name, field in six.iteritems(expected_item.fields):
+            for field_name, field in expected_item.fields.items():
                 if (expected_item.scope_ids.usage_id, field_name) in self.field_exclusions:
                     continue
                 if (None, field_name) in self.field_exclusions:
@@ -428,8 +425,8 @@ class CourseComparisonTest(TestCase):
 
         expected_filename = expected_asset.pop('filename')
         actual_filename = actual_asset.pop('filename')
-        assert text_type(expected_key) == expected_filename
-        assert text_type(actual_key) == actual_filename
+        assert str(expected_key) == expected_filename
+        assert str(actual_key) == actual_filename
         assert expected_asset == actual_asset
 
     def _assertAssetsEqual(self, expected_course_key, expected_assets, actual_course_key, actual_assets):  # pylint: disable=invalid-name
diff --git a/common/lib/xmodule/xmodule/tests/helpers.py b/common/lib/xmodule/xmodule/tests/helpers.py
index 63d8c0bdd4e1067a3e253396745b46c8cb31a685..42156049fdc5d331adacd07c2a9579ad10f3de97 100644
--- a/common/lib/xmodule/xmodule/tests/helpers.py
+++ b/common/lib/xmodule/xmodule/tests/helpers.py
@@ -36,7 +36,7 @@ class StubUserService(UserService):
 
     def __init__(self, is_anonymous=False, **kwargs):
         self.is_anonymous = is_anonymous
-        super(StubUserService, self).__init__(**kwargs)  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__(**kwargs)
 
     def get_current_user(self):
         """
diff --git a/common/lib/xmodule/xmodule/tests/test_annotatable_module.py b/common/lib/xmodule/xmodule/tests/test_annotatable_module.py
index c7e909f111b27c63ffd291ee89935399269a835a..5cdbac7b62656b25d5008937e74da7eaf5780cc1 100644
--- a/common/lib/xmodule/xmodule/tests/test_annotatable_module.py
+++ b/common/lib/xmodule/xmodule/tests/test_annotatable_module.py
@@ -68,7 +68,7 @@ class AnnotatableBlockTestCase(unittest.TestCase):  # lint-amnesty, pylint: disa
 
         for color in self.annotatable.HIGHLIGHT_COLORS:
             el = etree.fromstring(xml.format(highlight=color))
-            value = 'annotatable-span highlight highlight-{highlight}'.format(highlight=color)
+            value = f'annotatable-span highlight highlight-{color}'
 
             expected_attr = {
                 'class': {
@@ -126,7 +126,7 @@ class AnnotatableBlockTestCase(unittest.TestCase):  # lint-amnesty, pylint: disa
     def test_extract_instructions(self):
         xmltree = etree.fromstring(self.sample_xml)
 
-        expected_xml = u"<div>Read the text.</div>"
+        expected_xml = "<div>Read the text.</div>"
         actual_xml = self.annotatable._extract_instructions(xmltree)  # lint-amnesty, pylint: disable=protected-access
         assert actual_xml is not None
         assert expected_xml.strip() == actual_xml.strip()
diff --git a/common/lib/xmodule/xmodule/tests/test_annotator_mixin.py b/common/lib/xmodule/xmodule/tests/test_annotator_mixin.py
index 813e265d8e95551c450f0b0bc6216acb4214288e..baaa7ad5d905e4b30c68bed549ad4cbdca559790 100644
--- a/common/lib/xmodule/xmodule/tests/test_annotator_mixin.py
+++ b/common/lib/xmodule/xmodule/tests/test_annotator_mixin.py
@@ -30,7 +30,7 @@ class HelperFunctionTest(unittest.TestCase):
         """
         xmltree = etree.fromstring(self.sample_xml)
 
-        expected_xml = u"<div><p>Helper Test Instructions.</p></div>"
+        expected_xml = "<div><p>Helper Test Instructions.</p></div>"
         actual_xml = get_instructions(xmltree)
         assert actual_xml is not None
         assert expected_xml.strip() == actual_xml.strip()
diff --git a/common/lib/xmodule/xmodule/tests/test_capa_module.py b/common/lib/xmodule/xmodule/tests/test_capa_module.py
index 30ee3e078263f3db6da77c888c8ce461ac45ddc8..a3351277b3a647fc5df7834f9dcb5ead8d43d2be 100644
--- a/common/lib/xmodule/xmodule/tests/test_capa_module.py
+++ b/common/lib/xmodule/xmodule/tests/test_capa_module.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 """
 Tests of the Capa XModule
 """
@@ -11,19 +10,17 @@ import os
 import random
 import textwrap
 import unittest
+from unittest.mock import DEFAULT, Mock, patch
 
 import pytest
 import ddt
 import requests
-import six
 import webob
 from django.utils.encoding import smart_text
 from edx_user_state_client.interface import XBlockUserState
 from lxml import etree
-from mock import DEFAULT, Mock, patch
 from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
 from pytz import UTC
-from six.moves import range, zip
 from webob.multidict import MultiDict
 from xblock.field_data import DictFieldData
 from xblock.fields import ScopeIds
@@ -41,7 +38,7 @@ from ..capa_base import RANDOMIZATION, SHOWANSWER
 from . import get_test_system
 
 
-class CapaFactory(object):
+class CapaFactory:
     """
     A helper class to create problem modules with various parameters for testing.
     """
@@ -101,7 +98,7 @@ class CapaFactory(object):
         location = BlockUsageLocator(
             CourseLocator("edX", "capa_test", "2012_Fall", deprecated=True),
             "problem",
-            "SampleProblem{0}".format(cls.next_num()),
+            f"SampleProblem{cls.next_num()}",
             deprecated=True,
         )
         if xml is None:
@@ -182,7 +179,7 @@ if submission[0] == '':
 class ProblemBlockTest(unittest.TestCase):  # lint-amnesty, pylint: disable=missing-class-docstring
 
     def setUp(self):
-        super(ProblemBlockTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
 
         now = datetime.datetime.now(UTC)
         day_delta = datetime.timedelta(days=1)
@@ -861,8 +858,8 @@ class ProblemBlockTest(unittest.TestCase):  # lint-amnesty, pylint: disable=miss
 
         assert xqueue_interface._http_post.call_count == 1
         _, kwargs = xqueue_interface._http_post.call_args
-        six.assertCountEqual(self, fpaths, list(kwargs['files'].keys()))
-        for fpath, fileobj in six.iteritems(kwargs['files']):
+        self.assertCountEqual(fpaths, list(kwargs['files'].keys()))
+        for fpath, fileobj in kwargs['files'].items():
             assert fpath == fileobj.name
 
     def test_submit_problem_with_files_as_xblock(self):
@@ -894,8 +891,8 @@ class ProblemBlockTest(unittest.TestCase):  # lint-amnesty, pylint: disable=miss
 
         assert xqueue_interface._http_post.call_count == 1
         _, kwargs = xqueue_interface._http_post.call_args
-        six.assertCountEqual(self, fnames, list(kwargs['files'].keys()))
-        for fpath, fileobj in six.iteritems(kwargs['files']):
+        self.assertCountEqual(fnames, list(kwargs['files'].keys()))
+        for fpath, fileobj in kwargs['files'].items():
             assert fpath == fileobj.name
 
     def test_submit_problem_error(self):
@@ -947,7 +944,7 @@ class ProblemBlockTest(unittest.TestCase):  # lint-amnesty, pylint: disable=miss
                         '  File "<string>", line 65, in check_func\\n'
                         'Exception: Couldn\'t execute jailed code\\n\' with status code: 1', )
                 except ResponseError as err:
-                    mock_grade.side_effect = exception_class(six.text_type(err))
+                    mock_grade.side_effect = exception_class(str(err))
                 get_request_dict = {CapaFactory.input_key(): '3.14'}
                 result = module.submit_problem(get_request_dict)
 
@@ -974,7 +971,7 @@ class ProblemBlockTest(unittest.TestCase):  # lint-amnesty, pylint: disable=miss
 
         # Simulate answering a problem that raises the exception
         with patch('capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
-            error_msg = u"Superterrible error happened: ☠"
+            error_msg = "Superterrible error happened: ☠"
             mock_grade.side_effect = Exception(error_msg)
 
             get_request_dict = {CapaFactory.input_key(): '3.14'}
@@ -1009,13 +1006,13 @@ class ProblemBlockTest(unittest.TestCase):  # lint-amnesty, pylint: disable=miss
 
             # Simulate answering a problem that raises the exception
             with patch('capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
-                mock_grade.side_effect = exception_class(u"ȧƈƈḗƞŧḗḓ ŧḗẋŧ ƒǿř ŧḗşŧīƞɠ")
+                mock_grade.side_effect = exception_class("ȧƈƈḗƞŧḗḓ ŧḗẋŧ ƒǿř ŧḗşŧīƞɠ")
 
                 get_request_dict = {CapaFactory.input_key(): '3.14'}
                 result = module.submit_problem(get_request_dict)
 
             # Expect an AJAX alert message in 'success'
-            expected_msg = u'ȧƈƈḗƞŧḗḓ ŧḗẋŧ ƒǿř ŧḗşŧīƞɠ'
+            expected_msg = 'ȧƈƈḗƞŧḗḓ ŧḗẋŧ ƒǿř ŧḗşŧīƞɠ'
 
             assert expected_msg == result['success']
 
@@ -1241,7 +1238,7 @@ class ProblemBlockTest(unittest.TestCase):  # lint-amnesty, pylint: disable=miss
 
         # Simulate answering a problem that raises the exception
         with patch('capa.capa_problem.LoncapaProblem.get_grade_from_current_answers') as mock_rescore:
-            mock_rescore.side_effect = exception_class(u'test error \u03a9')
+            mock_rescore.side_effect = exception_class('test error \u03a9')
             with pytest.raises(exception_class):
                 module.rescore(only_if_higher=False)
 
@@ -1710,7 +1707,7 @@ class ProblemBlockTest(unittest.TestCase):  # lint-amnesty, pylint: disable=miss
 
         # Simulate throwing an exception when the capa problem
         # is asked to render itself as HTML
-        error_msg = u"Superterrible error happened: ☠"
+        error_msg = "Superterrible error happened: ☠"
         module.lcp.get_html = Mock(side_effect=Exception(error_msg))
 
         # Stub out the get_test_system rendering function
@@ -2527,7 +2524,7 @@ class ProblemBlockXMLTest(unittest.TestCase):  # lint-amnesty, pylint: disable=m
         self.assertDictEqual(
             indexing_result, {
                 'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
-                'problem_types': set(["optionresponse", "multiplechoiceresponse"]),
+                'problem_types': {"optionresponse", "multiplechoiceresponse"},
                 'content': {
                     'display_name': name,
                     'capa_content': " Label Some comment Donut Buggy '1','2' "
@@ -2569,7 +2566,7 @@ class ProblemBlockXMLTest(unittest.TestCase):  # lint-amnesty, pylint: disable=m
     def test_indexing_checkboxes(self):
         name = "Checkboxes"
         descriptor = self._create_descriptor(self.sample_checkbox_problem_xml, name=name)
-        capa_content = textwrap.dedent(u"""
+        capa_content = textwrap.dedent("""
             Title
             Description
             Example
@@ -2856,7 +2853,7 @@ class ProblemCheckTrackingTest(unittest.TestCase):
     """
 
     def setUp(self):
-        super(ProblemCheckTrackingTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.maxDiff = None
 
     def test_choice_answer_text(self):
@@ -2909,14 +2906,14 @@ class ProblemCheckTrackingTest(unittest.TestCase):
                                         'group_label': '',
                                         'variant': ''},
                 factory.answer_key(3): {'question': 'Which piece of furniture is built for sitting?',
-                                        'answer': u'<text>a table</text>',
+                                        'answer': '<text>a table</text>',
                                         'response_type': 'multiplechoiceresponse',
                                         'input_type': 'choicegroup',
                                         'correct': False,
                                         'group_label': '',
                                         'variant': ''},
                 factory.answer_key(4): {'question': 'Which of the following are musical instruments?',
-                                        'answer': [u'a piano', u'a tree'],
+                                        'answer': ['a piano', 'a tree'],
                                         'response_type': 'choiceresponse',
                                         'input_type': 'checkboxgroup',
                                         'correct': False,
@@ -3160,14 +3157,14 @@ class ProblemBlockReportGenerationTest(unittest.TestCase):
 
     def _mock_user_state_generator(self, user_count=1, response_count=10):
         for uid in range(user_count):
-            yield self._user_state(username='user{}'.format(uid), response_count=response_count)
+            yield self._user_state(username=f'user{uid}', response_count=response_count)
 
     def _user_state(self, username='testuser', response_count=10, suffix=''):
         return XBlockUserState(
             username=username,
             state={
                 'student_answers': {
-                    '{}_answerid_{}{}'.format(username, aid, suffix): '{}_answer_{}'.format(username, aid)
+                    f'{username}_answerid_{aid}{suffix}': f'{username}_answer_{aid}'
                     for aid in range(response_count)
                 },
                 'seed': 1,
diff --git a/common/lib/xmodule/xmodule/tests/test_conditional.py b/common/lib/xmodule/xmodule/tests/test_conditional.py
index 02d2a746f89d355b2eb5d02205da95cfebd03758..201c5fd6c5bc8e3aba73d913b636c970f6cbb823 100644
--- a/common/lib/xmodule/xmodule/tests/test_conditional.py
+++ b/common/lib/xmodule/xmodule/tests/test_conditional.py
@@ -2,13 +2,12 @@
 
 import json
 import unittest
+from unittest.mock import Mock, patch
 
 from fs.memoryfs import MemoryFS
 from lxml import etree
-from mock import Mock, patch
 from opaque_keys.edx.keys import CourseKey
 from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
-from six import text_type
 from web_fragments.fragment import Fragment
 from xblock.field_data import DictFieldData
 from xblock.fields import ScopeIds
@@ -33,7 +32,7 @@ class DummySystem(ImportSystem):  # lint-amnesty, pylint: disable=abstract-metho
 
         xmlstore = XMLModuleStore("data_dir", source_dirs=[], load_error_modules=load_error_modules)
 
-        super(DummySystem, self).__init__(  # lint-amnesty, pylint: disable=super-with-arguments
+        super().__init__(
             xmlstore=xmlstore,
             course_id=CourseKey.from_string('/'.join([ORG, COURSE, 'test_run'])),
             course_dir='test_dir',
@@ -52,7 +51,7 @@ class ConditionalBlockFactory(xml.XmlImportFactory):
     tag = 'conditional'
 
 
-class ConditionalFactory(object):
+class ConditionalFactory:
     """
     A helper class to create a conditional module and associated source and child modules
     to allow for testing.
@@ -89,7 +88,7 @@ class ConditionalFactory(object):
         # construct other descriptors:
         child_descriptor = Mock(name='child_descriptor')
         child_descriptor.visible_to_staff_only = False
-        child_descriptor._xmodule.student_view.return_value = Fragment(content=u'<p>This is a secret</p>')  # lint-amnesty, pylint: disable=protected-access
+        child_descriptor._xmodule.student_view.return_value = Fragment(content='<p>This is a secret</p>')  # lint-amnesty, pylint: disable=protected-access
         child_descriptor.student_view = child_descriptor._xmodule.student_view  # lint-amnesty, pylint: disable=protected-access
         child_descriptor.displayable_items.return_value = [child_descriptor]
         child_descriptor.runtime = descriptor_system
@@ -149,7 +148,7 @@ class ConditionalBlockBasicTest(unittest.TestCase):
     """
 
     def setUp(self):
-        super(ConditionalBlockBasicTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.test_system = get_test_system()
 
     def test_icon_class(self):
@@ -168,8 +167,8 @@ class ConditionalBlockBasicTest(unittest.TestCase):
         html = modules['cond_module'].render(STUDENT_VIEW).content
         expected = modules['cond_module'].xmodule_runtime.render_template('conditional_ajax.html', {
             'ajax_url': modules['cond_module'].ajax_url,
-            'element_id': u'i4x-edX-conditional_test-conditional-SampleConditional',
-            'depends': u'i4x-edX-conditional_test-problem-SampleProblem',
+            'element_id': 'i4x-edX-conditional_test-conditional-SampleConditional',
+            'depends': 'i4x-edX-conditional_test-problem-SampleProblem',
         })
         assert expected == html
 
@@ -226,12 +225,12 @@ class ConditionalBlockXmlTest(unittest.TestCase):
         return DummySystem(load_error_modules)
 
     def setUp(self):
-        super(ConditionalBlockXmlTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
+        super().setUp()
         self.test_system = get_test_system()
 
     def get_course(self, name):
         """Get a test course by directory name.  If there's more than one, error."""
-        print("Importing {0}".format(name))
+        print(f"Importing {name}")
 
         modulestore = XMLModuleStore(DATA_DIR, source_dirs=[name])
         courses = modulestore.get_courses()
@@ -280,9 +279,9 @@ class ConditionalBlockXmlTest(unittest.TestCase):
             'conditional_ajax.html',
             {
                 # Test ajax url is just usage-id / handler_name
-                'ajax_url': '{}/xmodule_handler'.format(text_type(location)),
-                'element_id': u'i4x-HarvardX-ER22x-conditional-condone',
-                'depends': u'i4x-HarvardX-ER22x-problem-choiceprob'
+                'ajax_url': '{}/xmodule_handler'.format(str(location)),
+                'element_id': 'i4x-HarvardX-ER22x-conditional-condone',
+                'depends': 'i4x-HarvardX-ER22x-problem-choiceprob'
             }
         )
         assert html == html_expect
@@ -443,7 +442,7 @@ class ConditionalBlockStudioTest(XModuleXmlImportTest):
         """
         self.conditional.sources_list = None
         validation = self.conditional.validate()
-        assert validation.summary.text == u'This component has no source components configured yet.'
+        assert validation.summary.text == 'This component has no source components configured yet.'
         assert validation.summary.type == StudioValidationMessage.NOT_CONFIGURED
         assert validation.summary.action_class == 'edit-button'
-        assert validation.summary.action_label == u'Configure list of sources'
+        assert validation.summary.action_label == 'Configure list of sources'