From 5d2b0e83469109cc6302965037cded9cdae51804 Mon Sep 17 00:00:00 2001 From: "M. Zulqarnain" Date: Wed, 17 Mar 2021 17:28:23 +0500 Subject: [PATCH] refactor: pyupgrade in content_libraries and contentserver apps (#26892) --- .../core/djangoapps/content_libraries/api.py | 19 +++++----- .../core/djangoapps/content_libraries/apps.py | 2 +- .../content_libraries/libraries_index.py | 2 +- .../content_libraries/library_bundle.py | 12 +++---- .../content_libraries/library_context.py | 2 +- .../commands/reindex_content_library.py | 4 +-- .../migrations/0001_initial.py | 3 +- .../migrations/0002_group_permissions.py | 3 +- .../djangoapps/content_libraries/models.py | 5 ++- .../content_libraries/serializers.py | 2 +- .../content_libraries/tests/base.py | 3 +- .../tests/test_content_libraries.py | 3 +- .../tests/test_libraries_index.py | 2 +- .../content_libraries/tests/test_runtime.py | 9 +++-- .../tests/test_static_assets.py | 7 ++-- .../tests/user_state_block.py | 1 - .../djangoapps/content_libraries/views.py | 2 +- .../core/djangoapps/contentserver/caching.py | 10 ++---- .../djangoapps/contentserver/middleware.py | 20 +++++------ .../contentserver/migrations/0001_initial.py | 3 +- .../migrations/0002_cdnuseragentsconfig.py | 5 +-- .../core/djangoapps/contentserver/models.py | 25 +++++-------- .../contentserver/test/test_contentserver.py | 35 +++++++++---------- 23 files changed, 76 insertions(+), 103 deletions(-) diff --git a/openedx/core/djangoapps/content_libraries/api.py b/openedx/core/djangoapps/content_libraries/api.py index 75f0510fe2..821f591645 100644 --- a/openedx/core/djangoapps/content_libraries/api.py +++ b/openedx/core/djangoapps/content_libraries/api.py @@ -51,7 +51,6 @@ from lxml import etree from opaque_keys.edx.keys import LearningContextKey from opaque_keys.edx.locator import BundleDefinitionLocator, LibraryLocatorV2, LibraryUsageLocatorV2 from organizations.models import Organization -import six from xblock.core import XBlock from xblock.exceptions import XBlockNotFoundError @@ -552,10 +551,10 @@ def update_library( "slug": ref.slug, } if title is not None: - assert isinstance(title, six.string_types) + assert isinstance(title, str) fields["title"] = title if description is not None: - assert isinstance(description, six.string_types) + assert isinstance(description, str) fields["description"] = description update_bundle(ref.bundle_uuid, **fields) CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=ref.library_key) @@ -704,7 +703,7 @@ def set_library_block_olx(usage_key, new_olx_str): # Verify that the OLX parses, at least as generic XML: node = etree.fromstring(new_olx_str) if node.tag != block_type: - raise ValueError("Invalid root tag in OLX, expected {}".format(block_type)) + raise ValueError(f"Invalid root tag in OLX, expected {block_type}") # Write the new XML/OLX file into the library bundle's draft draft = get_or_create_bundle_draft(metadata.def_key.bundle_uuid, DRAFT_NAME) write_draft_file(draft.uuid, metadata.def_key.olx_path, new_olx_str.encode('utf-8')) @@ -734,7 +733,7 @@ def create_library_block(library_key, block_type, definition_id): total_blocks = len(lib_bundle.get_top_level_usages()) if total_blocks + 1 > settings.MAX_BLOCKS_PER_CONTENT_LIBRARY: raise BlockLimitReachedError( - _(u"Library cannot have more than {} XBlocks").format(settings.MAX_BLOCKS_PER_CONTENT_LIBRARY) + _("Library cannot have more than {} XBlocks").format(settings.MAX_BLOCKS_PER_CONTENT_LIBRARY) ) # Make sure the proposed ID will be valid: validate_unicode_slug(definition_id) @@ -749,10 +748,10 @@ def create_library_block(library_key, block_type, definition_id): ) library_context = get_learning_context_impl(usage_key) if library_context.definition_for_usage(usage_key) is not None: - raise LibraryBlockAlreadyExists("An XBlock with ID '{}' already exists".format(new_usage_id)) + raise LibraryBlockAlreadyExists(f"An XBlock with ID '{new_usage_id}' already exists") - new_definition_xml = '<{}/>'.format(block_type) # xss-lint: disable=python-wrap-html - path = "{}/{}/definition.xml".format(block_type, definition_id) + new_definition_xml = f'<{block_type}/>' # xss-lint: disable=python-wrap-html + path = f"{block_type}/{definition_id}/definition.xml" # Write the new XML/OLX file into the library bundle's draft draft = get_or_create_bundle_draft(ref.bundle_uuid, DRAFT_NAME) write_draft_file(draft.uuid, path, new_definition_xml.encode('utf-8')) @@ -871,7 +870,7 @@ def add_library_block_static_asset_file(usage_key, file_name, file_content): video_block = UsageKey.from_string("lb:VideoTeam:python-intro:video:1") add_library_block_static_asset_file(video_block, "subtitles-en.srt", subtitles.encode('utf-8')) """ - assert isinstance(file_content, six.binary_type) + assert isinstance(file_content, bytes) def_key, lib_bundle = _lookup_usage_key(usage_key) if file_name != file_name.strip().strip('/'): raise InvalidNameError("file name cannot start/end with / or whitespace.") @@ -953,7 +952,7 @@ def get_bundle_links(library_key): links = blockstore_cache.get_bundle_draft_direct_links_cached(ref.bundle_uuid, DRAFT_NAME) results = [] # To be able to quickly get the library ID from the bundle ID for links which point to other libraries, build a map: - bundle_uuids = set(link_data.bundle_uuid for link_data in links.values()) + bundle_uuids = {link_data.bundle_uuid for link_data in links.values()} libraries_linked = { lib.bundle_uuid: lib for lib in ContentLibrary.objects.select_related('org').filter(bundle_uuid__in=bundle_uuids) diff --git a/openedx/core/djangoapps/content_libraries/apps.py b/openedx/core/djangoapps/content_libraries/apps.py index 37ac8898f0..bece3dc641 100644 --- a/openedx/core/djangoapps/content_libraries/apps.py +++ b/openedx/core/djangoapps/content_libraries/apps.py @@ -23,7 +23,7 @@ class ContentLibrariesConfig(AppConfig): PluginURLs.CONFIG: { ProjectType.CMS: { # The namespace to provide to django's urls.include. - PluginURLs.NAMESPACE: u'content_libraries', + PluginURLs.NAMESPACE: 'content_libraries', }, }, PluginSettings.CONFIG: { diff --git a/openedx/core/djangoapps/content_libraries/libraries_index.py b/openedx/core/djangoapps/content_libraries/libraries_index.py index c34c02298d..b7a682fa5a 100644 --- a/openedx/core/djangoapps/content_libraries/libraries_index.py +++ b/openedx/core/djangoapps/content_libraries/libraries_index.py @@ -130,7 +130,7 @@ class SearchIndexerBase(ABC): text_search_normalised = text_search.translate(text_search.maketrans('', '', RESERVED_CHARACTERS + '"')) text_search_normalised = text_search_normalised.replace('-', ' ') # Wrap with asterix to enable partial matches - text_search_normalised = "*{}*".format(text_search_normalised) + text_search_normalised = f"*{text_search_normalised}*" terms = [ { 'terms': { diff --git a/openedx/core/djangoapps/content_libraries/library_bundle.py b/openedx/core/djangoapps/content_libraries/library_bundle.py index 98716a3615..ac96ce1508 100644 --- a/openedx/core/djangoapps/content_libraries/library_bundle.py +++ b/openedx/core/djangoapps/content_libraries/library_bundle.py @@ -92,7 +92,7 @@ def usage_for_child_include(parent_usage, parent_definition, parsed_include): ) -class LibraryBundle(object): +class LibraryBundle: """ Wrapper around a Content Library Blockstore bundle that contains OLX. """ @@ -149,7 +149,7 @@ class LibraryBundle(object): version_arg = {"draft_name": self.draft_name} else: version_arg = {"bundle_version": get_bundle_version_number(self.bundle_uuid)} - olx_path = "{}/{}/definition.xml".format(usage_key.block_type, usage_key.usage_id) + olx_path = f"{usage_key.block_type}/{usage_key.usage_id}/definition.xml" try: get_bundle_file_metadata_with_cache(self.bundle_uuid, olx_path, **version_arg) return BundleDefinitionLocator(self.bundle_uuid, usage_key.block_type, olx_path, **version_arg) @@ -209,7 +209,7 @@ class LibraryBundle(object): try: xml_node = xml_for_definition(def_key) except: # pylint:disable=bare-except - log.exception("Unable to load definition {}".format(def_key)) + log.exception(f"Unable to load definition {def_key}") return for child in xml_node: @@ -220,7 +220,7 @@ class LibraryBundle(object): child_usage = usage_for_child_include(usage_key, def_key, parsed_include) child_def_key = definition_for_include(parsed_include, def_key) except BundleFormatException: - log.exception("Unable to parse a child of {}".format(def_key)) + log.exception(f"Unable to parse a child of {def_key}") continue usages_found[child_usage] = child_def_key add_definitions_children(child_usage, child_def_key) @@ -314,8 +314,8 @@ class LibraryBundle(object): new_links = set(get_bundle_direct_links_with_cache(self.bundle_uuid, draft_name=self.draft_name).items()) has_unpublished_changes = new_links != old_links - published_file_paths = set(f.path for f in get_bundle_files_cached(self.bundle_uuid)) - draft_file_paths = set(f.path for f in draft_files) + published_file_paths = {f.path for f in get_bundle_files_cached(self.bundle_uuid)} + draft_file_paths = {f.path for f in draft_files} for file_path in published_file_paths: if file_path not in draft_file_paths: has_unpublished_changes = True diff --git a/openedx/core/djangoapps/content_libraries/library_context.py b/openedx/core/djangoapps/content_libraries/library_context.py index b65aa12f16..f9316dc972 100644 --- a/openedx/core/djangoapps/content_libraries/library_context.py +++ b/openedx/core/djangoapps/content_libraries/library_context.py @@ -27,7 +27,7 @@ class LibraryContextImpl(LearningContext): """ def __init__(self, **kwargs): - super(LibraryContextImpl, self).__init__(**kwargs) # lint-amnesty, pylint: disable=super-with-arguments + super().__init__(**kwargs) self.use_draft = kwargs.get('use_draft', None) def can_edit_block(self, user, usage_key): diff --git a/openedx/core/djangoapps/content_libraries/management/commands/reindex_content_library.py b/openedx/core/djangoapps/content_libraries/management/commands/reindex_content_library.py index a316729d6c..6c3c8874e8 100644 --- a/openedx/core/djangoapps/content_libraries/management/commands/reindex_content_library.py +++ b/openedx/core/djangoapps/content_libraries/management/commands/reindex_content_library.py @@ -31,8 +31,8 @@ class Command(BaseCommand): ./manage.py reindex_content_library --clear-all - clear all libraries indexes """ help = dedent(__doc__) - CONFIRMATION_PROMPT_CLEAR = u"This will clear all indexed libraries from elasticsearch. Do you want to continue?" - CONFIRMATION_PROMPT_ALL = u"Reindexing all libraries might be a time consuming operation. Do you want to continue?" + CONFIRMATION_PROMPT_CLEAR = "This will clear all indexed libraries from elasticsearch. Do you want to continue?" + CONFIRMATION_PROMPT_ALL = "Reindexing all libraries might be a time consuming operation. Do you want to continue?" def add_arguments(self, parser): parser.add_argument( diff --git a/openedx/core/djangoapps/content_libraries/migrations/0001_initial.py b/openedx/core/djangoapps/content_libraries/migrations/0001_initial.py index 46952d94b4..d36a4406c1 100644 --- a/openedx/core/djangoapps/content_libraries/migrations/0001_initial.py +++ b/openedx/core/djangoapps/content_libraries/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.23 on 2019-08-28 20:27 @@ -51,6 +50,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='contentlibrary', - unique_together=set([('org', 'slug')]), + unique_together={('org', 'slug')}, ), ] diff --git a/openedx/core/djangoapps/content_libraries/migrations/0002_group_permissions.py b/openedx/core/djangoapps/content_libraries/migrations/0002_group_permissions.py index 3c7e3e6e5c..8c417983ce 100644 --- a/openedx/core/djangoapps/content_libraries/migrations/0002_group_permissions.py +++ b/openedx/core/djangoapps/content_libraries/migrations/0002_group_permissions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.26 on 2019-12-11 19:20 @@ -40,6 +39,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='contentlibrarypermission', - unique_together=set([('library', 'user'), ('library', 'group')]), + unique_together={('library', 'user'), ('library', 'group')}, ), ] diff --git a/openedx/core/djangoapps/content_libraries/models.py b/openedx/core/djangoapps/content_libraries/models.py index 11dd330745..a8ffa653bb 100644 --- a/openedx/core/djangoapps/content_libraries/models.py +++ b/openedx/core/djangoapps/content_libraries/models.py @@ -12,7 +12,6 @@ from openedx.core.djangoapps.content_libraries.constants import ( ALL_RIGHTS_RESERVED, ) from organizations.models import Organization # lint-amnesty, pylint: disable=wrong-import-order -import six # lint-amnesty, pylint: disable=wrong-import-order User = get_user_model() @@ -84,7 +83,7 @@ class ContentLibrary(models.Model): return LibraryLocatorV2(org=self.org.short_name, slug=self.slug) def __str__(self): - return "ContentLibrary ({})".format(six.text_type(self.library_key)) + return "ContentLibrary ({})".format(str(self.library_key)) class ContentLibraryPermission(models.Model): @@ -127,4 +126,4 @@ class ContentLibraryPermission(models.Model): def __str__(self): who = self.user.username if self.user else self.group.name - return "ContentLibraryPermission ({} for {})".format(self.access_level, who) + return f"ContentLibraryPermission ({self.access_level} for {who})" diff --git a/openedx/core/djangoapps/content_libraries/serializers.py b/openedx/core/djangoapps/content_libraries/serializers.py index 83bc207551..0d4d80566f 100644 --- a/openedx/core/djangoapps/content_libraries/serializers.py +++ b/openedx/core/djangoapps/content_libraries/serializers.py @@ -176,7 +176,7 @@ class LibraryXBlockStaticFileSerializer(serializers.Serializer): """ Generate the serialized representation of this static asset file. """ - result = super(LibraryXBlockStaticFileSerializer, self).to_representation(instance) # lint-amnesty, pylint: disable=super-with-arguments + result = super().to_representation(instance) # Make sure the URL is one that will work from the user's browser, # not one that only works from within a docker container: result['url'] = blockstore_api.force_browser_url(result['url']) diff --git a/openedx/core/djangoapps/content_libraries/tests/base.py b/openedx/core/djangoapps/content_libraries/tests/base.py index c83eb30540..435985571e 100644 --- a/openedx/core/djangoapps/content_libraries/tests/base.py +++ b/openedx/core/djangoapps/content_libraries/tests/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Tests for Blockstore-based Content Libraries """ @@ -6,10 +5,10 @@ from contextlib import contextmanager from io import BytesIO from urllib.parse import urlencode import unittest +from unittest.mock import patch from django.conf import settings from django.test.utils import override_settings -from mock import patch from organizations.models import Organization from rest_framework.test import APITestCase, APIClient from search.search_engine_base import SearchEngine diff --git a/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py b/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py index 1ab5d88eae..f615863ed1 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py @@ -1,14 +1,13 @@ -# -*- coding: utf-8 -*- """ Tests for Blockstore-based Content Libraries """ from uuid import UUID +from unittest.mock import patch import ddt from django.conf import settings from django.contrib.auth.models import Group from django.test.utils import override_settings -from mock import patch from organizations.models import Organization from openedx.core.djangoapps.content_libraries.libraries_index import LibraryBlockIndexer, ContentLibraryIndexer diff --git a/openedx/core/djangoapps/content_libraries/tests/test_libraries_index.py b/openedx/core/djangoapps/content_libraries/tests/test_libraries_index.py index 6d6cae7516..194786db51 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_libraries_index.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_libraries_index.py @@ -1,11 +1,11 @@ """ Testing indexing of blockstore based content libraries """ +from unittest.mock import patch from django.conf import settings from django.core.management import call_command from django.test.utils import override_settings -from mock import patch from opaque_keys.edx.locator import LibraryLocatorV2, LibraryUsageLocatorV2 from search.search_engine_base import SearchEngine diff --git a/openedx/core/djangoapps/content_libraries/tests/test_runtime.py b/openedx/core/djangoapps/content_libraries/tests/test_runtime.py index 76a182fe8a..dc7aadab27 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_runtime.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_runtime.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Test the Blockstore-based XBlock runtime and content libraries together. """ @@ -29,13 +28,13 @@ from common.djangoapps.student.tests.factories import UserFactory from xmodule.unit_block import UnitBlock -class ContentLibraryContentTestMixin(object): +class ContentLibraryContentTestMixin: """ Mixin for content library tests that creates two students and a library. """ @classmethod def setUpClass(cls): - super(ContentLibraryContentTestMixin, cls).setUpClass() + super().setUpClass() # Create a couple students that the tests can use cls.student_a = UserFactory.create(username="Alice", email="alice@example.com", password="edx") cls.student_b = UserFactory.create(username="Bob", email="bob@example.com", password="edx") @@ -398,7 +397,7 @@ class ContentLibraryXBlockUserStateTest(ContentLibraryContentTestMixin, TestCase client = APIClient() client.login(username=self.student_a.username, password='edx') student_view_result = client.get(URL_BLOCK_RENDER_VIEW.format(block_key=block_id, view_name='student_view')) - problem_key = "input_{}_2_1".format(block_id) + problem_key = f"input_{block_id}_2_1" assert problem_key in student_view_result.data['content'] # And submit a wrong answer: @@ -488,7 +487,7 @@ class ContentLibraryXBlockCompletionTest(ContentLibraryContentTestMixin, Complet """ def setUp(self): - super(ContentLibraryXBlockCompletionTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() # Enable the completion waffle flag for these tests self.override_waffle_switch(True) diff --git a/openedx/core/djangoapps/content_libraries/tests/test_static_assets.py b/openedx/core/djangoapps/content_libraries/tests/test_static_assets.py index a81fff2732..0342e27ebd 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_static_assets.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_static_assets.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Tests for static asset files in Blockstore-based Content Libraries """ @@ -11,17 +10,17 @@ from openedx.core.djangoapps.content_libraries.tests.base import ContentLibrarie # Binary data representing an SVG image file SVG_DATA = """ SVG is 🔥 -""".encode('utf-8') +""".encode() # part of an .srt transcript file -TRANSCRIPT_DATA = """1 +TRANSCRIPT_DATA = b"""1 00:00:00,260 --> 00:00:01,510 Welcome to edX. 2 00:00:01,510 --> 00:00:04,480 I'm Anant Agarwal, I'm the president of edX, -""".encode('utf-8') +""" class ContentLibrariesStaticAssetsTest(ContentLibrariesRestApiTest): diff --git a/openedx/core/djangoapps/content_libraries/tests/user_state_block.py b/openedx/core/djangoapps/content_libraries/tests/user_state_block.py index 3bcd77f0df..16329a18ca 100644 --- a/openedx/core/djangoapps/content_libraries/tests/user_state_block.py +++ b/openedx/core/djangoapps/content_libraries/tests/user_state_block.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Block for testing variously scoped XBlock fields. """ diff --git a/openedx/core/djangoapps/content_libraries/views.py b/openedx/core/djangoapps/content_libraries/views.py index b1a596a228..150b9a47b8 100644 --- a/openedx/core/djangoapps/content_libraries/views.py +++ b/openedx/core/djangoapps/content_libraries/views.py @@ -167,7 +167,7 @@ class LibraryRootView(APIView): ensure_organization(org_name) except InvalidOrganizationException: raise ValidationError( # lint-amnesty, pylint: disable=raise-missing-from - detail={"org": "No such organization '{}' found.".format(org_name)} + detail={"org": f"No such organization '{org_name}' found."} ) org = Organization.objects.get(short_name=org_name) try: diff --git a/openedx/core/djangoapps/contentserver/caching.py b/openedx/core/djangoapps/contentserver/caching.py index 3b3fa43f54..8468c09a4c 100644 --- a/openedx/core/djangoapps/contentserver/caching.py +++ b/openedx/core/djangoapps/contentserver/caching.py @@ -1,10 +1,6 @@ """ Helper functions for caching course assets. """ - - -import six - from django.core.cache import caches from django.core.cache.backends.base import InvalidCacheBackendError from opaque_keys import InvalidKeyError @@ -23,14 +19,14 @@ def set_cached_content(content): """ Stores the given piece of content in the cache, using its location as the key. """ - CONTENT_CACHE.set(six.text_type(content.location).encode("utf-8"), content, version=STATIC_CONTENT_VERSION) + CONTENT_CACHE.set(str(content.location).encode("utf-8"), content, version=STATIC_CONTENT_VERSION) def get_cached_content(location): """ Retrieves the given piece of content by its location if cached. """ - return CONTENT_CACHE.get(six.text_type(location).encode("utf-8"), version=STATIC_CONTENT_VERSION) + return CONTENT_CACHE.get(str(location).encode("utf-8"), version=STATIC_CONTENT_VERSION) def del_cached_content(location): @@ -42,7 +38,7 @@ def del_cached_content(location): """ def location_str(loc): """Force the location to a Unicode string.""" - return six.text_type(loc).encode("utf-8") + return str(loc).encode("utf-8") locations = [location_str(location)] try: diff --git a/openedx/core/djangoapps/contentserver/middleware.py b/openedx/core/djangoapps/contentserver/middleware.py index 937e2a8226..fa7ac983a0 100644 --- a/openedx/core/djangoapps/contentserver/middleware.py +++ b/openedx/core/djangoapps/contentserver/middleware.py @@ -6,7 +6,6 @@ Middleware to serve assets. import datetime import logging -import six from django.http import ( HttpResponse, HttpResponseBadRequest, @@ -18,7 +17,6 @@ from django.http import ( from django.utils.deprecation import MiddlewareMixin from opaque_keys import InvalidKeyError from opaque_keys.edx.locator import AssetLocator -from six import text_type from openedx.core.djangoapps.header_control import force_header_for_response from common.djangoapps.student.models import CourseEnrollment @@ -41,7 +39,7 @@ except ImportError: # TODO: Soon as we have a reasonable way to serialize/deserialize AssetKeys, we need # to change this file so instead of using course_id_partial, we're just using asset keys -HTTP_DATE_FORMAT = u"%a, %d %b %Y %H:%M:%S GMT" +HTTP_DATE_FORMAT = "%a, %d %b %Y %H:%M:%S GMT" class StaticContentServer(MiddlewareMixin): @@ -144,19 +142,19 @@ class StaticContentServer(MiddlewareMixin): except ValueError as exception: # If the header field is syntactically invalid it should be ignored. log.exception( - u"%s in Range header: %s for content: %s", - text_type(exception), header_value, six.text_type(loc) + "%s in Range header: %s for content: %s", + str(exception), header_value, str(loc) ) else: if unit != 'bytes': # Only accept ranges in bytes - log.warning(u"Unknown unit in Range header: %s for content: %s", header_value, text_type(loc)) + log.warning("Unknown unit in Range header: %s for content: %s", header_value, str(loc)) elif len(ranges) > 1: # According to Http/1.1 spec content for multiple ranges should be sent as a multipart message. # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16 # But we send back the full content. log.warning( - u"More than 1 ranges in Range header: %s for content: %s", header_value, text_type(loc) + "More than 1 ranges in Range header: %s for content: %s", header_value, str(loc) ) else: first, last = ranges[0] @@ -164,7 +162,7 @@ class StaticContentServer(MiddlewareMixin): if 0 <= first <= last < content.length: # If the byte range is satisfiable response = HttpResponse(content.stream_data_in_range(first, last)) - response['Content-Range'] = u'bytes {first}-{last}/{length}'.format( + response['Content-Range'] = 'bytes {first}-{last}/{length}'.format( first=first, last=last, length=content.length ) response['Content-Length'] = str(last - first + 1) @@ -174,8 +172,8 @@ class StaticContentServer(MiddlewareMixin): newrelic.agent.add_custom_parameter('contentserver.ranged', True) else: log.warning( - u"Cannot satisfy ranges in Range header: %s for content: %s", - header_value, text_type(loc) + "Cannot satisfy ranges in Range header: %s for content: %s", + header_value, str(loc) ) return HttpResponse(status=416) # Requested Range Not Satisfiable @@ -219,7 +217,7 @@ class StaticContentServer(MiddlewareMixin): newrelic.agent.add_custom_parameter('contentserver.cacheable', True) response['Expires'] = StaticContentServer.get_expiration_value(datetime.datetime.utcnow(), cache_ttl) - response['Cache-Control'] = u"public, max-age={ttl}, s-maxage={ttl}".format(ttl=cache_ttl) + response['Cache-Control'] = "public, max-age={ttl}, s-maxage={ttl}".format(ttl=cache_ttl) elif is_locked: if newrelic: newrelic.agent.add_custom_parameter('contentserver.cacheable', False) diff --git a/openedx/core/djangoapps/contentserver/migrations/0001_initial.py b/openedx/core/djangoapps/contentserver/migrations/0001_initial.py index 73c156f189..c43f49f8ce 100644 --- a/openedx/core/djangoapps/contentserver/migrations/0001_initial.py +++ b/openedx/core/djangoapps/contentserver/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- #pylint: skip-file @@ -20,7 +19,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), - ('cache_ttl', models.PositiveIntegerField(default=0, help_text=u'The time, in seconds, to report that a course asset is allowed to be cached for.')), + ('cache_ttl', models.PositiveIntegerField(default=0, help_text='The time, in seconds, to report that a course asset is allowed to be cached for.')), ('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')), ], ), diff --git a/openedx/core/djangoapps/contentserver/migrations/0002_cdnuseragentsconfig.py b/openedx/core/djangoapps/contentserver/migrations/0002_cdnuseragentsconfig.py index be2a423efa..f0d579ff5a 100644 --- a/openedx/core/djangoapps/contentserver/migrations/0002_cdnuseragentsconfig.py +++ b/openedx/core/djangoapps/contentserver/migrations/0002_cdnuseragentsconfig.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from django.db import migrations, models import django.db.models.deletion from django.conf import settings @@ -20,7 +17,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), - ('cdn_user_agents', models.TextField(default=u'Amazon CloudFront', help_text=u'A newline-separated list of user agents that should be considered CDNs.')), + ('cdn_user_agents', models.TextField(default='Amazon CloudFront', help_text='A newline-separated list of user agents that should be considered CDNs.')), ('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')), ], ), diff --git a/openedx/core/djangoapps/contentserver/models.py b/openedx/core/djangoapps/contentserver/models.py index 3991902f94..c4f5c5f643 100644 --- a/openedx/core/djangoapps/contentserver/models.py +++ b/openedx/core/djangoapps/contentserver/models.py @@ -1,16 +1,10 @@ """ Models for contentserver """ - - -import six - from config_models.models import ConfigurationModel from django.db.models.fields import PositiveIntegerField, TextField -from django.utils.encoding import python_2_unicode_compatible -@python_2_unicode_compatible class CourseAssetCacheTtlConfig(ConfigurationModel): """ Configuration for the TTL of course assets. @@ -18,12 +12,12 @@ class CourseAssetCacheTtlConfig(ConfigurationModel): .. no_pii: """ - class Meta(object): + class Meta: app_label = 'contentserver' cache_ttl = PositiveIntegerField( default=0, - help_text=u"The time, in seconds, to report that a course asset is allowed to be cached for." + help_text="The time, in seconds, to report that a course asset is allowed to be cached for." ) @classmethod @@ -32,13 +26,12 @@ class CourseAssetCacheTtlConfig(ConfigurationModel): return cls.current().cache_ttl def __repr__(self): - return ''.format(self.get_cache_ttl()) + return f'' def __str__(self): - return six.text_type(repr(self)) + return str(repr(self)) -@python_2_unicode_compatible class CdnUserAgentsConfig(ConfigurationModel): """ Configuration for the user agents we expect to see from CDNs. @@ -46,12 +39,12 @@ class CdnUserAgentsConfig(ConfigurationModel): .. no_pii: """ - class Meta(object): + class Meta: app_label = 'contentserver' cdn_user_agents = TextField( - default=u'Amazon CloudFront', - help_text=u"A newline-separated list of user agents that should be considered CDNs." + default='Amazon CloudFront', + help_text="A newline-separated list of user agents that should be considered CDNs." ) @classmethod @@ -60,7 +53,7 @@ class CdnUserAgentsConfig(ConfigurationModel): return cls.current().cdn_user_agents def __repr__(self): - return ''.format(self.get_cdn_user_agents()) + return f'' def __str__(self): - return six.text_type(repr(self)) + return str(repr(self)) diff --git a/openedx/core/djangoapps/contentserver/test/test_contentserver.py b/openedx/core/djangoapps/contentserver/test/test_contentserver.py index 32f79c738a..2fcbd1cb34 100644 --- a/openedx/core/djangoapps/contentserver/test/test_contentserver.py +++ b/openedx/core/djangoapps/contentserver/test/test_contentserver.py @@ -6,17 +6,16 @@ Tests for StaticContentServer import copy import datetime -import ddt -import logging # lint-amnesty, pylint: disable=wrong-import-order -import six -import unittest # lint-amnesty, pylint: disable=wrong-import-order -from uuid import uuid4 # lint-amnesty, pylint: disable=wrong-import-order +import logging +import unittest +from unittest.mock import patch +from uuid import uuid4 +import ddt from django.conf import settings from django.test import RequestFactory from django.test.client import Client from django.test.utils import override_settings -from mock import patch from xmodule.contentstore.django import contentstore from xmodule.contentstore.content import StaticContent, VERSIONED_ASSETS_PREFIX @@ -62,7 +61,7 @@ def get_old_style_versioned_asset_url(asset_path): try: locator = StaticContent.get_location_from_path(asset_path) content = AssetManager.find(locator, as_stream=True) - return u'{}/{}{}'.format(VERSIONED_ASSETS_PREFIX, content.content_digest, asset_path) + return f'{VERSIONED_ASSETS_PREFIX}/{content.content_digest}{asset_path}' except (InvalidKeyError, ItemNotFoundError): pass @@ -78,7 +77,7 @@ class ContentStoreToyCourseTest(SharedModuleStoreTestCase): @classmethod def setUpClass(cls): - super(ContentStoreToyCourseTest, cls).setUpClass() + super().setUpClass() cls.contentstore = contentstore() cls.modulestore = modulestore() @@ -92,14 +91,14 @@ class ContentStoreToyCourseTest(SharedModuleStoreTestCase): # A locked asset cls.locked_asset = cls.course_key.make_asset_key('asset', 'sample_static.html') - cls.url_locked = six.text_type(cls.locked_asset) + cls.url_locked = str(cls.locked_asset) cls.url_locked_versioned = get_versioned_asset_url(cls.url_locked) cls.url_locked_versioned_old_style = get_old_style_versioned_asset_url(cls.url_locked) cls.contentstore.set_attr(cls.locked_asset, 'locked', True) # An unlocked asset cls.unlocked_asset = cls.course_key.make_asset_key('asset', 'another_static.txt') - cls.url_unlocked = six.text_type(cls.unlocked_asset) + cls.url_unlocked = str(cls.unlocked_asset) cls.url_unlocked_versioned = get_versioned_asset_url(cls.url_unlocked) cls.url_unlocked_versioned_old_style = get_old_style_versioned_asset_url(cls.url_unlocked) cls.length_unlocked = cls.contentstore.get_attr(cls.unlocked_asset, 'length') @@ -108,7 +107,7 @@ class ContentStoreToyCourseTest(SharedModuleStoreTestCase): """ Create user and login. """ - super(ContentStoreToyCourseTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.staff_usr = AdminFactory.create() self.non_staff_usr = UserFactory.create() @@ -220,8 +219,8 @@ class ContentStoreToyCourseTest(SharedModuleStoreTestCase): assert resp.status_code == 206 # HTTP_206_PARTIAL_CONTENT assert resp['Content-Range'] ==\ - u'bytes {first}-{last}/{length}'.format(first=0, last=(self.length_unlocked - 1), - length=self.length_unlocked) + 'bytes {first}-{last}/{length}'.format(first=0, last=(self.length_unlocked - 1), + length=self.length_unlocked) assert resp['Content-Length'] == str(self.length_unlocked) def test_range_request_partial_file(self): @@ -237,10 +236,10 @@ class ContentStoreToyCourseTest(SharedModuleStoreTestCase): assert resp.status_code == 206 # HTTP_206_PARTIAL_CONTENT - assert resp['Content-Range'] == u'bytes {first}-{last}/{length}'.format(first=first_byte, - last=last_byte, - length=self.length_unlocked) - assert resp['Content-Length'] == str(((last_byte - first_byte) + 1)) + assert resp['Content-Range'] == 'bytes {first}-{last}/{length}'.format(first=first_byte, + last=last_byte, + length=self.length_unlocked) + assert resp['Content-Length'] == str((last_byte - first_byte) + 1) def test_range_request_multiple_ranges(self): """ @@ -413,7 +412,7 @@ class ParseRangeHeaderTestCase(unittest.TestCase): """ def setUp(self): - super(ParseRangeHeaderTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.content_length = 10000 def test_bytes_unit(self):