refactor: pyupgrade in content_libraries and contentserver apps (#26892)

This commit is contained in:
M. Zulqarnain
2021-03-17 17:28:23 +05:00
committed by GitHub
parent 6266caf143
commit 5d2b0e8346
23 changed files with 76 additions and 103 deletions

View File

@@ -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)

View File

@@ -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: {

View File

@@ -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': {

View File

@@ -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

View File

@@ -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):

View File

@@ -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(

View File

@@ -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')},
),
]

View File

@@ -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')},
),
]

View File

@@ -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})"

View File

@@ -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'])

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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 xmlns="http://www.w3.org/2000/svg" height="30" width="100">
<text x="0" y="15" fill="red">SVG is 🔥</text>
</svg>""".encode('utf-8')
</svg>""".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):

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Block for testing variously scoped XBlock fields.
"""

View File

@@ -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:

View File

@@ -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:

View File

@@ -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)

View File

@@ -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')),
],
),

View File

@@ -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')),
],
),

View File

@@ -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 '<CourseAssetCacheTtlConfig(cache_ttl={})>'.format(self.get_cache_ttl())
return f'<CourseAssetCacheTtlConfig(cache_ttl={self.get_cache_ttl()})>'
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 '<WhitelistedCdnConfig(cdn_user_agents={})>'.format(self.get_cdn_user_agents())
return f'<WhitelistedCdnConfig(cdn_user_agents={self.get_cdn_user_agents()})>'
def __str__(self):
return six.text_type(repr(self))
return str(repr(self))

View File

@@ -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):