refactor: ran pyupgrade on lms/djangoapps/course_api (#26735)
This commit is contained in:
@@ -3,32 +3,30 @@ Course API
|
||||
"""
|
||||
import logging
|
||||
|
||||
from edx_django_utils.monitoring import function_trace
|
||||
from edx_when.api import get_dates_for_course
|
||||
import search
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AnonymousUser, User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.urls import reverse
|
||||
from edx_django_utils.monitoring import function_trace
|
||||
from edx_when.api import get_dates_for_course
|
||||
from opaque_keys.edx.django.models import CourseKeyField
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
import search
|
||||
import six
|
||||
|
||||
from common.djangoapps.student.models import CourseAccessRole
|
||||
from common.djangoapps.student.roles import GlobalStaff
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from lms.djangoapps.courseware.courses import (
|
||||
get_course_overview_with_access,
|
||||
get_courses,
|
||||
get_permission_for_course_about
|
||||
)
|
||||
from opaque_keys.edx.django.models import CourseKeyField # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.lib.api.view_utils import LazySequence
|
||||
from common.djangoapps.student.models import CourseAccessRole
|
||||
from common.djangoapps.student.roles import GlobalStaff
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
|
||||
from .permissions import can_view_courses_for_username
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
|
||||
|
||||
|
||||
@@ -100,7 +98,7 @@ def _filter_by_search(course_queryset, search_term):
|
||||
return LazySequence(
|
||||
(
|
||||
course for course in course_queryset
|
||||
if six.text_type(course.id) in search_courses_ids
|
||||
if str(course.id) in search_courses_ids
|
||||
),
|
||||
est_len=len(course_queryset)
|
||||
)
|
||||
@@ -235,12 +233,12 @@ def get_due_dates(request, course_key, user):
|
||||
store = modulestore()
|
||||
|
||||
due_dates = []
|
||||
for (block_key, date_type), date in six.iteritems(dates):
|
||||
for (block_key, date_type), date in dates.items():
|
||||
if date_type == 'due':
|
||||
try:
|
||||
block_display_name = store.get_item(block_key).display_name
|
||||
except ItemNotFoundError:
|
||||
logger.exception('Failed to get block for due date item with key: {}'.format(block_key))
|
||||
logger.exception(f'Failed to get block for due date item with key: {block_key}')
|
||||
block_display_name = UNKNOWN_BLOCK_DISPLAY_NAME
|
||||
|
||||
# get url to the block in the course
|
||||
|
||||
@@ -48,7 +48,7 @@ class BlockListGetForm(Form):
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
raise ValidationError("'{}' is not a valid depth value.".format(value)) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise ValidationError(f"'{value}' is not a valid depth value.") # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
def clean_requested_fields(self):
|
||||
"""
|
||||
@@ -83,7 +83,7 @@ class BlockListGetForm(Form):
|
||||
"""
|
||||
Return cleaned data, including additional requested fields.
|
||||
"""
|
||||
cleaned_data = super(BlockListGetForm, self).clean() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
cleaned_data = super().clean()
|
||||
|
||||
# Add additional requested_fields that are specified as separate
|
||||
# parameters, if they were requested.
|
||||
|
||||
@@ -4,13 +4,15 @@ Encapsulates permissions checks for Course Blocks API
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.roles import CourseStaffRole
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from lms.djangoapps.courseware.access_response import AccessResponse
|
||||
from lms.djangoapps.courseware.access_utils import ACCESS_DENIED, ACCESS_GRANTED, check_public_access
|
||||
from lms.djangoapps.courseware.exceptions import CourseRunNotFound
|
||||
from lms.djangoapps.courseware.courses import get_course
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.roles import CourseStaffRole
|
||||
from lms.djangoapps.courseware.exceptions import CourseRunNotFound
|
||||
from openedx.core.djangoapps.content.course_overviews.models import \
|
||||
CourseOverview # lint-amnesty, pylint: disable=unused-import
|
||||
from xmodule.course_module import COURSE_VISIBILITY_PUBLIC
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ Serializers for Course Blocks related return objects.
|
||||
"""
|
||||
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from rest_framework import serializers
|
||||
from rest_framework.reverse import reverse
|
||||
@@ -12,13 +11,13 @@ from lms.djangoapps.course_blocks.transformers.visibility import VisibilityTrans
|
||||
|
||||
from .transformers.block_completion import BlockCompletionTransformer
|
||||
from .transformers.block_counts import BlockCountsTransformer
|
||||
from .transformers.extra_fields import ExtraFieldsTransformer
|
||||
from .transformers.milestones import MilestonesAndSpecialExamsTransformer
|
||||
from .transformers.navigation import BlockNavigationTransformer
|
||||
from .transformers.student_view import StudentViewTransformer
|
||||
from .transformers.extra_fields import ExtraFieldsTransformer
|
||||
|
||||
|
||||
class SupportedFieldType(object):
|
||||
class SupportedFieldType:
|
||||
"""
|
||||
Metadata about fields supported by different transformers
|
||||
"""
|
||||
@@ -141,16 +140,16 @@ class BlockSerializer(serializers.Serializer): # pylint: disable=abstract-metho
|
||||
authorization_denial_message = block_structure.get_xblock_field(block_key, 'authorization_denial_message')
|
||||
|
||||
data = {
|
||||
'id': six.text_type(block_key),
|
||||
'block_id': six.text_type(block_key.block_id),
|
||||
'id': str(block_key),
|
||||
'block_id': str(block_key.block_id),
|
||||
'lms_web_url': reverse(
|
||||
'jump_to',
|
||||
kwargs={'course_id': six.text_type(block_key.course_key), 'location': six.text_type(block_key)},
|
||||
kwargs={'course_id': str(block_key.course_key), 'location': str(block_key)},
|
||||
request=self.context['request'],
|
||||
),
|
||||
'student_view_url': reverse(
|
||||
'render_xblock',
|
||||
kwargs={'usage_key_string': six.text_type(block_key)},
|
||||
kwargs={'usage_key_string': str(block_key)},
|
||||
request=self.context['request'],
|
||||
),
|
||||
}
|
||||
@@ -158,7 +157,7 @@ class BlockSerializer(serializers.Serializer): # pylint: disable=abstract-metho
|
||||
if settings.FEATURES.get("ENABLE_LTI_PROVIDER") and 'lti_url' in self.context['requested_fields']:
|
||||
data['lti_url'] = reverse(
|
||||
'lti_provider_launch',
|
||||
kwargs={'course_id': six.text_type(block_key.course_key), 'usage_id': six.text_type(block_key)},
|
||||
kwargs={'course_id': str(block_key.course_key), 'usage_id': str(block_key)},
|
||||
request=self.context['request'],
|
||||
)
|
||||
|
||||
@@ -178,7 +177,7 @@ class BlockSerializer(serializers.Serializer): # pylint: disable=abstract-metho
|
||||
if 'children' in self.context['requested_fields']:
|
||||
children = block_structure.get_children(block_key)
|
||||
if children:
|
||||
data['children'] = [six.text_type(child) for child in children]
|
||||
data['children'] = [str(child) for child in children]
|
||||
|
||||
if authorization_denial_reason and authorization_denial_message:
|
||||
data['authorization_denial_reason'] = authorization_denial_reason
|
||||
@@ -205,6 +204,6 @@ class BlockDictSerializer(serializers.Serializer): # pylint: disable=abstract-m
|
||||
Serialize to a dictionary of blocks keyed by the block's usage_key.
|
||||
"""
|
||||
return {
|
||||
six.text_type(block_key): BlockSerializer(block_key, context=self.context).data
|
||||
str(block_key): BlockSerializer(block_key, context=self.context).data
|
||||
for block_key in structure
|
||||
}
|
||||
|
||||
@@ -4,20 +4,19 @@ Tests for Blocks api.py
|
||||
|
||||
|
||||
from itertools import product
|
||||
from unittest.mock import patch
|
||||
|
||||
import ddt
|
||||
import six
|
||||
from django.test.client import RequestFactory
|
||||
from edx_toggles.toggles.testutils import override_waffle_switch
|
||||
from mock import patch
|
||||
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from openedx.core.djangoapps.content.block_structure.api import clear_course_from_cache
|
||||
from openedx.core.djangoapps.content.block_structure.config import STORAGE_BACKING_FOR_CACHE
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import SampleCourseFactory, check_mongo_calls
|
||||
from xmodule.modulestore.tests.sample_courses import BlockInfo
|
||||
from openedx.core.djangoapps.content.block_structure.api import clear_course_from_cache
|
||||
from openedx.core.djangoapps.content.block_structure.config import STORAGE_BACKING_FOR_CACHE
|
||||
|
||||
from ..api import get_blocks
|
||||
|
||||
@@ -29,7 +28,7 @@ class TestGetBlocks(SharedModuleStoreTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestGetBlocks, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
with cls.store.default_store(ModuleStoreEnum.Type.split):
|
||||
cls.course = SampleCourseFactory.create()
|
||||
|
||||
@@ -39,22 +38,22 @@ class TestGetBlocks(SharedModuleStoreTestCase):
|
||||
cls.store.update_item(cls.html_block, ModuleStoreEnum.UserID.test)
|
||||
|
||||
def setUp(self):
|
||||
super(TestGetBlocks, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory.create()
|
||||
self.request = RequestFactory().get("/dummy")
|
||||
self.request.user = self.user
|
||||
|
||||
def test_basic(self):
|
||||
blocks = get_blocks(self.request, self.course.location, self.user)
|
||||
assert blocks['root'] == six.text_type(self.course.location)
|
||||
assert blocks['root'] == str(self.course.location)
|
||||
|
||||
# subtract for (1) the orphaned course About block and (2) the hidden Html block
|
||||
assert len(blocks['blocks']) == (len(self.store.get_items(self.course.id)) - 2)
|
||||
assert six.text_type(self.html_block.location) not in blocks['blocks']
|
||||
assert str(self.html_block.location) not in blocks['blocks']
|
||||
|
||||
def test_no_user(self):
|
||||
blocks = get_blocks(self.request, self.course.location)
|
||||
assert six.text_type(self.html_block.location) in blocks['blocks']
|
||||
assert str(self.html_block.location) in blocks['blocks']
|
||||
|
||||
def test_access_before_api_transformer_order(self):
|
||||
"""
|
||||
@@ -65,16 +64,16 @@ class TestGetBlocks(SharedModuleStoreTestCase):
|
||||
vertical_block = self.store.get_item(self.course.id.make_usage_key('vertical', 'vertical_x1a'))
|
||||
problem_block = self.store.get_item(self.course.id.make_usage_key('problem', 'problem_x1a_1'))
|
||||
|
||||
vertical_descendants = blocks['blocks'][six.text_type(vertical_block.location)]['descendants']
|
||||
vertical_descendants = blocks['blocks'][str(vertical_block.location)]['descendants']
|
||||
|
||||
assert six.text_type(problem_block.location) in vertical_descendants
|
||||
assert six.text_type(self.html_block.location) not in vertical_descendants
|
||||
assert str(problem_block.location) in vertical_descendants
|
||||
assert str(self.html_block.location) not in vertical_descendants
|
||||
|
||||
def test_sub_structure(self):
|
||||
sequential_block = self.store.get_item(self.course.id.make_usage_key('sequential', 'sequential_y1'))
|
||||
|
||||
blocks = get_blocks(self.request, sequential_block.location, self.user)
|
||||
assert blocks['root'] == six.text_type(sequential_block.location)
|
||||
assert blocks['root'] == str(sequential_block.location)
|
||||
assert len(blocks['blocks']) == 5
|
||||
|
||||
for block_type, block_name, is_inside_of_structure in (
|
||||
@@ -85,9 +84,9 @@ class TestGetBlocks(SharedModuleStoreTestCase):
|
||||
):
|
||||
block = self.store.get_item(self.course.id.make_usage_key(block_type, block_name))
|
||||
if is_inside_of_structure:
|
||||
assert six.text_type(block.location) in blocks['blocks']
|
||||
assert str(block.location) in blocks['blocks']
|
||||
else:
|
||||
assert six.text_type(block.location) not in blocks['blocks']
|
||||
assert str(block.location) not in blocks['blocks']
|
||||
|
||||
def test_filtering_by_block_types(self):
|
||||
sequential_block = self.store.get_item(self.course.id.make_usage_key('sequential', 'sequential_y1'))
|
||||
@@ -96,7 +95,7 @@ class TestGetBlocks(SharedModuleStoreTestCase):
|
||||
blocks = get_blocks(self.request, sequential_block.location, self.user, requested_fields=['type'])
|
||||
assert len(blocks['blocks']) == 5
|
||||
found_not_problem = False
|
||||
for block in six.itervalues(blocks['blocks']):
|
||||
for block in blocks['blocks'].values():
|
||||
if block['type'] != 'problem':
|
||||
found_not_problem = True
|
||||
assert found_not_problem
|
||||
@@ -105,7 +104,7 @@ class TestGetBlocks(SharedModuleStoreTestCase):
|
||||
blocks = get_blocks(self.request, sequential_block.location, self.user,
|
||||
block_types_filter=['problem'], requested_fields=['type'])
|
||||
assert len(blocks['blocks']) == 3
|
||||
for block in six.itervalues(blocks['blocks']):
|
||||
for block in blocks['blocks'].values():
|
||||
assert block['type'] == 'problem'
|
||||
|
||||
|
||||
@@ -118,7 +117,7 @@ class TestGetBlocksMobileHack(SharedModuleStoreTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestGetBlocksMobileHack, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
with cls.store.default_store(ModuleStoreEnum.Type.split):
|
||||
cls.course = SampleCourseFactory.create(
|
||||
block_info_tree=[
|
||||
@@ -139,7 +138,7 @@ class TestGetBlocksMobileHack(SharedModuleStoreTestCase):
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
super(TestGetBlocksMobileHack, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory.create()
|
||||
self.request = RequestFactory().get("/dummy")
|
||||
self.request.user = self.user
|
||||
@@ -151,9 +150,9 @@ class TestGetBlocksMobileHack(SharedModuleStoreTestCase):
|
||||
def test_empty_containers(self, is_mobile, container_type):
|
||||
with patch('lms.djangoapps.course_api.blocks.api.is_request_from_mobile_app', return_value=is_mobile):
|
||||
blocks = get_blocks(self.request, self.course.location)
|
||||
full_container_key = self.course.id.make_usage_key(container_type, 'full_{}'.format(container_type))
|
||||
full_container_key = self.course.id.make_usage_key(container_type, f'full_{container_type}')
|
||||
assert str(full_container_key) in blocks['blocks']
|
||||
empty_container_key = self.course.id.make_usage_key(container_type, 'empty_{}'.format(container_type))
|
||||
empty_container_key = self.course.id.make_usage_key(container_type, f'empty_{container_type}')
|
||||
assert_containment = self.assertNotIn if is_mobile else self.assertIn
|
||||
assert_containment(str(empty_container_key), blocks['blocks'])
|
||||
|
||||
@@ -180,7 +179,7 @@ class TestGetBlocksMobileHack(SharedModuleStoreTestCase):
|
||||
)
|
||||
video_block_key = str(self.course.id.make_usage_key('video', 'sample_video'))
|
||||
video_block_data = blocks['blocks'][video_block_key]
|
||||
for video_data in six.itervalues(video_block_data['student_view_data']['encoded_videos']):
|
||||
for video_data in video_block_data['student_view_data']['encoded_videos'].values():
|
||||
assert 'cloudfront' not in video_data['url']
|
||||
|
||||
|
||||
@@ -193,7 +192,7 @@ class TestGetBlocksQueryCountsBase(SharedModuleStoreTestCase):
|
||||
ENABLED_SIGNALS = ['course_published']
|
||||
|
||||
def setUp(self):
|
||||
super(TestGetBlocksQueryCountsBase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.user = UserFactory.create()
|
||||
self.request = RequestFactory().get("/dummy")
|
||||
|
||||
@@ -3,17 +3,17 @@ Tests for Course Blocks forms
|
||||
"""
|
||||
|
||||
|
||||
from urllib.parse import urlencode
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
import six
|
||||
from six.moves.urllib.parse import urlencode
|
||||
from django.http import Http404, QueryDict
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
|
||||
from openedx.core.djangoapps.util.test_forms import FormTestMixin
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from openedx.core.djangoapps.util.test_forms import FormTestMixin
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
@@ -30,12 +30,12 @@ class TestBlockListGetForm(FormTestMixin, SharedModuleStoreTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestBlockListGetForm, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
def setUp(self):
|
||||
super(TestBlockListGetForm, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.student = UserFactory.create()
|
||||
self.student2 = UserFactory.create()
|
||||
@@ -49,7 +49,7 @@ class TestBlockListGetForm(FormTestMixin, SharedModuleStoreTestCase):
|
||||
self.form_data = QueryDict(
|
||||
urlencode({
|
||||
'username': self.student.username,
|
||||
'usage_key': six.text_type(usage_key),
|
||||
'usage_key': str(usage_key),
|
||||
}),
|
||||
mutable=True,
|
||||
)
|
||||
|
||||
@@ -3,13 +3,12 @@ Tests for Course Blocks serializers
|
||||
"""
|
||||
|
||||
|
||||
import six
|
||||
from mock import MagicMock
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from lms.djangoapps.course_blocks.api import get_course_block_access_transformers, get_course_blocks
|
||||
from openedx.core.djangoapps.content.block_structure.transformers import BlockStructureTransformers
|
||||
from common.djangoapps.student.roles import CourseStaffRole
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from lms.djangoapps.course_blocks.api import get_course_block_access_transformers, get_course_blocks
|
||||
from openedx.core.djangoapps.content.block_structure.transformers import BlockStructureTransformers
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import ToyCourseFactory
|
||||
@@ -26,7 +25,7 @@ class TestBlockSerializerBase(SharedModuleStoreTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestBlockSerializerBase, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
|
||||
cls.course = ToyCourseFactory.create()
|
||||
|
||||
@@ -37,7 +36,7 @@ class TestBlockSerializerBase(SharedModuleStoreTestCase):
|
||||
cls.store.update_item(cls.html_block, ModuleStoreEnum.UserID.test)
|
||||
|
||||
def setUp(self):
|
||||
super(TestBlockSerializerBase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.user = UserFactory.create()
|
||||
|
||||
@@ -65,7 +64,7 @@ class TestBlockSerializerBase(SharedModuleStoreTestCase):
|
||||
"""
|
||||
block_key = deserialize_usage_key(block_key_string, self.course.id)
|
||||
assert self.block_structure.get_xblock_field(block_key, 'category') == serialized_block['type']
|
||||
assert set(six.iterkeys(serialized_block)) == {'id', 'block_id', 'type', 'lms_web_url', 'student_view_url'}
|
||||
assert set(serialized_block.keys()) == {'id', 'block_id', 'type', 'lms_web_url', 'student_view_url'}
|
||||
|
||||
def add_additional_requested_fields(self, context=None):
|
||||
"""
|
||||
@@ -90,7 +89,7 @@ class TestBlockSerializerBase(SharedModuleStoreTestCase):
|
||||
Verifies the given serialized_block when additional fields are requested.
|
||||
"""
|
||||
assert {'id', 'type', 'lms_web_url', 'student_view_url', 'display_name', 'graded', 'student_view_multi_device',
|
||||
'lti_url', 'visible_to_staff_only'} <= set(six.iterkeys(serialized_block))
|
||||
'lti_url', 'visible_to_staff_only'} <= set(serialized_block.keys())
|
||||
|
||||
# video blocks should have student_view_data
|
||||
if serialized_block['type'] == 'video':
|
||||
@@ -131,7 +130,7 @@ class TestBlockSerializerBase(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Test fields accessed by a staff user
|
||||
"""
|
||||
if serialized_block['id'] == six.text_type(self.html_block.location):
|
||||
if serialized_block['id'] == str(self.html_block.location):
|
||||
assert serialized_block['visible_to_staff_only']
|
||||
else:
|
||||
assert not serialized_block['visible_to_staff_only']
|
||||
@@ -197,10 +196,10 @@ class TestBlockDictSerializer(TestBlockSerializerBase):
|
||||
serializer = self.create_serializer()
|
||||
|
||||
# verify root
|
||||
assert serializer.data['root'] == six.text_type(self.block_structure.root_block_usage_key)
|
||||
assert serializer.data['root'] == str(self.block_structure.root_block_usage_key)
|
||||
|
||||
# verify blocks
|
||||
for block_key_string, serialized_block in six.iteritems(serializer.data['blocks']):
|
||||
for block_key_string, serialized_block in serializer.data['blocks'].items():
|
||||
assert serialized_block['id'] == block_key_string
|
||||
self.assert_basic_block(block_key_string, serialized_block)
|
||||
assert len(serializer.data['blocks']) == 28
|
||||
@@ -208,7 +207,7 @@ class TestBlockDictSerializer(TestBlockSerializerBase):
|
||||
def test_additional_requested_fields(self):
|
||||
self.add_additional_requested_fields()
|
||||
serializer = self.create_serializer()
|
||||
for serialized_block in six.itervalues(serializer.data['blocks']):
|
||||
for serialized_block in serializer.data['blocks'].values():
|
||||
self.assert_extended_block(serialized_block)
|
||||
assert len(serializer.data['blocks']) == 28
|
||||
|
||||
@@ -219,7 +218,7 @@ class TestBlockDictSerializer(TestBlockSerializerBase):
|
||||
context = self.create_staff_context()
|
||||
self.add_additional_requested_fields(context)
|
||||
serializer = self.create_serializer(context)
|
||||
for serialized_block in six.itervalues(serializer.data['blocks']):
|
||||
for serialized_block in serializer.data['blocks'].values():
|
||||
self.assert_extended_block(serialized_block)
|
||||
self.assert_staff_fields(serialized_block)
|
||||
assert len(serializer.data['blocks']) == 29
|
||||
|
||||
@@ -8,10 +8,10 @@ from unittest import mock
|
||||
from unittest.mock import Mock
|
||||
from urllib.parse import urlencode, urlunparse
|
||||
|
||||
from completion.test_utils import CompletionWaffleTestMixin, submit_completions_for_testing
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from completion.test_utils import CompletionWaffleTestMixin, submit_completions_for_testing
|
||||
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.tests.factories import AdminFactory, CourseEnrollmentFactory, UserFactory
|
||||
@@ -30,7 +30,7 @@ class TestBlocksView(SharedModuleStoreTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestBlocksView, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
|
||||
# create a toy course
|
||||
cls.course = ToyCourseFactory.create(
|
||||
@@ -40,15 +40,15 @@ class TestBlocksView(SharedModuleStoreTestCase):
|
||||
cls.course_key = cls.course.id
|
||||
cls.course_usage_key = cls.store.make_course_usage_key(cls.course_key)
|
||||
|
||||
cls.non_orphaned_block_usage_keys = set(
|
||||
cls.non_orphaned_block_usage_keys = {
|
||||
str(item.location)
|
||||
for item in cls.store.get_items(cls.course_key)
|
||||
# remove all orphaned items in the course, except for the root 'course' block
|
||||
if cls.store.get_parent_location(item.location) or item.category == 'course'
|
||||
)
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
super(TestBlocksView, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
# create and enroll user in the toy course
|
||||
self.user = UserFactory.create()
|
||||
@@ -126,7 +126,7 @@ class TestBlocksView(SharedModuleStoreTestCase):
|
||||
|
||||
if xblock.has_children:
|
||||
self.assertSetEqual(
|
||||
set(str(child.location) for child in xblock.get_children()),
|
||||
{str(child.location) for child in xblock.get_children()},
|
||||
set(block_data['children']),
|
||||
)
|
||||
|
||||
@@ -390,16 +390,16 @@ class TestBlocksInCourseView(TestBlocksView, CompletionWaffleTestMixin): # pyli
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestBlocksInCourseView, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse('blocks_in_course')
|
||||
self.query_params['course_id'] = str(self.course_key)
|
||||
self.override_waffle_switch(True)
|
||||
self.non_orphaned_raw_block_usage_keys = set(
|
||||
self.non_orphaned_raw_block_usage_keys = {
|
||||
item.location
|
||||
for item in self.store.get_items(self.course_key)
|
||||
# remove all orphaned items in the course, except for the root 'course' block
|
||||
if self.store.get_parent_location(item.location) or item.category == 'course'
|
||||
)
|
||||
}
|
||||
|
||||
def test_no_course_id(self):
|
||||
self.query_params.pop('course_id')
|
||||
|
||||
@@ -5,7 +5,7 @@ Toggles for Course API.
|
||||
|
||||
from edx_toggles.toggles import LegacyWaffleFlag, LegacyWaffleFlagNamespace
|
||||
|
||||
COURSE_BLOCKS_API_NAMESPACE = LegacyWaffleFlagNamespace(name=u'course_blocks_api')
|
||||
COURSE_BLOCKS_API_NAMESPACE = LegacyWaffleFlagNamespace(name='course_blocks_api')
|
||||
|
||||
# .. toggle_name: course_blocks_api.hide_access_denials
|
||||
# .. toggle_implementation: WaffleFlag
|
||||
@@ -18,6 +18,6 @@ COURSE_BLOCKS_API_NAMESPACE = LegacyWaffleFlagNamespace(name=u'course_blocks_api
|
||||
# .. toggle_tickets: None
|
||||
HIDE_ACCESS_DENIALS_FLAG = LegacyWaffleFlag(
|
||||
waffle_namespace=COURSE_BLOCKS_API_NAMESPACE,
|
||||
flag_name=u'hide_access_denials',
|
||||
flag_name='hide_access_denials',
|
||||
module_name=__name__,
|
||||
)
|
||||
|
||||
@@ -7,10 +7,10 @@ from openedx.core.djangoapps.content.block_structure.transformer import BlockStr
|
||||
|
||||
from .block_counts import BlockCountsTransformer
|
||||
from .block_depth import BlockDepthTransformer
|
||||
from .extra_fields import ExtraFieldsTransformer
|
||||
from .navigation import BlockNavigationTransformer
|
||||
from .student_view import StudentViewTransformer
|
||||
from .video_urls import VideoBlockURLTransformer
|
||||
from .extra_fields import ExtraFieldsTransformer
|
||||
|
||||
|
||||
class BlocksAPITransformer(BlockStructureTransformer):
|
||||
|
||||
@@ -5,14 +5,13 @@ Milestones Transformer
|
||||
|
||||
import logging
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from edx_proctoring.api import get_attempt_status_summary
|
||||
from edx_proctoring.exceptions import ProctoredExamNotFoundException
|
||||
|
||||
from openedx.core.djangoapps.content.block_structure.transformer import BlockStructureTransformer
|
||||
from common.djangoapps.student.models import EntranceExamConfiguration
|
||||
from common.djangoapps.util import milestones_helpers
|
||||
from openedx.core.djangoapps.content.block_structure.transformer import BlockStructureTransformer
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -102,8 +101,8 @@ class MilestonesAndSpecialExamsTransformer(BlockStructureTransformer):
|
||||
them from accessing this block.
|
||||
"""
|
||||
return bool(milestones_helpers.get_course_content_milestones(
|
||||
six.text_type(block_key.course_key),
|
||||
six.text_type(block_key),
|
||||
str(block_key.course_key),
|
||||
str(block_key),
|
||||
'requires',
|
||||
usage_info.user.id
|
||||
))
|
||||
@@ -120,8 +119,8 @@ class MilestonesAndSpecialExamsTransformer(BlockStructureTransformer):
|
||||
# This will return None, if (user, course_id, content_id) is not applicable.
|
||||
special_exam_attempt_context = get_attempt_status_summary(
|
||||
usage_info.user.id,
|
||||
six.text_type(block_key.course_key),
|
||||
six.text_type(block_key)
|
||||
str(block_key.course_key),
|
||||
str(block_key)
|
||||
)
|
||||
except ProctoredExamNotFoundException as ex:
|
||||
log.exception(ex)
|
||||
@@ -169,7 +168,7 @@ class MilestonesAndSpecialExamsTransformer(BlockStructureTransformer):
|
||||
if not required_content:
|
||||
return False
|
||||
|
||||
if block_key.block_type == 'chapter' and six.text_type(block_key) not in required_content:
|
||||
if block_key.block_type == 'chapter' and str(block_key) not in required_content:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -3,14 +3,12 @@ TODO
|
||||
"""
|
||||
|
||||
|
||||
import six
|
||||
|
||||
from openedx.core.djangoapps.content.block_structure.transformer import BlockStructureTransformer
|
||||
|
||||
from .block_depth import BlockDepthTransformer
|
||||
|
||||
|
||||
class DescendantList(object):
|
||||
class DescendantList:
|
||||
"""
|
||||
Contain
|
||||
"""
|
||||
@@ -76,7 +74,7 @@ class BlockNavigationTransformer(BlockStructureTransformer):
|
||||
# add self to parent's descendants
|
||||
for parent_desc_list in parents_descendants_list:
|
||||
if parent_desc_list is not None:
|
||||
parent_desc_list.items.append(six.text_type(block_key))
|
||||
parent_desc_list.items.append(str(block_key))
|
||||
|
||||
if BlockDepthTransformer.get_block_depth(block_structure, block_key) > self.nav_depth:
|
||||
children_descendants_list = parents_descendants_list
|
||||
|
||||
@@ -8,10 +8,10 @@ from completion.test_utils import CompletionWaffleTestMixin
|
||||
from xblock.completable import CompletableXBlockMixin, XBlockCompletionMode
|
||||
from xblock.core import XBlock
|
||||
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from lms.djangoapps.course_api.blocks.transformers.block_completion import BlockCompletionTransformer
|
||||
from lms.djangoapps.course_blocks.api import get_course_blocks
|
||||
from lms.djangoapps.course_blocks.transformers.tests.helpers import ModuleStoreTestCase, TransformerRegistryTestMixin
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ class BlockCompletionTransformerTestCase(TransformerRegistryTestMixin, Completio
|
||||
COMPLETION_TEST_VALUE = 0.4
|
||||
|
||||
def setUp(self):
|
||||
super(BlockCompletionTransformerTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory.create(password='test')
|
||||
# Set ENABLE_COMPLETION_TRACKING waffle switch to True
|
||||
self.override_waffle_switch(True)
|
||||
|
||||
@@ -18,7 +18,7 @@ class TestBlockCountsTransformer(ModuleStoreTestCase):
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestBlockCountsTransformer, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course_key = SampleCourseFactory.create().id
|
||||
self.course_usage_key = self.store.make_course_usage_key(self.course_key)
|
||||
self.block_structure = BlockStructureFactory.create_from_modulestore(self.course_usage_key, self.store)
|
||||
|
||||
@@ -30,7 +30,7 @@ class TestExtraFieldsTransformer(ModuleStoreTestCase):
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
super(TestExtraFieldsTransformer, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.course = SampleCourseFactory.create(
|
||||
other_course_settings=self.OTHER_COURSE_SETTINGS_DEFAULT
|
||||
|
||||
@@ -3,17 +3,17 @@ Tests for ProctoredExamTransformer.
|
||||
"""
|
||||
|
||||
|
||||
import ddt
|
||||
import six
|
||||
from milestones.tests.utils import MilestonesTestCaseMixin
|
||||
from mock import Mock, patch
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from lms.djangoapps.gating import api as lms_gating_api
|
||||
import ddt
|
||||
from milestones.tests.utils import MilestonesTestCaseMixin
|
||||
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory
|
||||
from lms.djangoapps.course_blocks.api import get_course_blocks
|
||||
from lms.djangoapps.course_blocks.transformers.tests.helpers import CourseStructureTestCase
|
||||
from lms.djangoapps.gating import api as lms_gating_api
|
||||
from openedx.core.djangoapps.content.block_structure.transformers import BlockStructureTransformers
|
||||
from openedx.core.lib.gating import api as gating_api
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory
|
||||
|
||||
from ..milestones import MilestonesAndSpecialExamsTransformer
|
||||
|
||||
@@ -30,7 +30,7 @@ class MilestonesTransformerTestCase(CourseStructureTestCase, MilestonesTestCaseM
|
||||
"""
|
||||
Setup course structure and create user for split test transformer test.
|
||||
"""
|
||||
super(MilestonesTransformerTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
# Build course.
|
||||
self.course_hierarchy = self.get_course_hierarchy()
|
||||
@@ -49,7 +49,7 @@ class MilestonesTransformerTestCase(CourseStructureTestCase, MilestonesTestCaseM
|
||||
gated_block: The block that should be inaccessible until gating_block is completed
|
||||
gating_block: The block that must be completed before access is granted
|
||||
"""
|
||||
gating_api.add_prerequisite(self.course.id, six.text_type(gating_block.location))
|
||||
gating_api.add_prerequisite(self.course.id, str(gating_block.location))
|
||||
gating_api.set_required_content(self.course.id, gated_block.location, gating_block.location, 100, 0)
|
||||
|
||||
ALL_BLOCKS = (
|
||||
|
||||
@@ -7,7 +7,6 @@ Tests for BlockNavigationTransformer.
|
||||
from unittest import TestCase
|
||||
|
||||
import ddt
|
||||
import six
|
||||
|
||||
from lms.djangoapps.course_api.blocks.transformers.block_depth import BlockDepthTransformer
|
||||
from lms.djangoapps.course_api.blocks.transformers.navigation import BlockNavigationTransformer
|
||||
@@ -57,7 +56,7 @@ class BlockNavigationTransformerTestCase(TestCase, ChildrenMapTestMixin):
|
||||
|
||||
for block_key, expected_nav in enumerate(expected_nav_map):
|
||||
self.assertSetEqual(
|
||||
set(six.text_type(block) for block in expected_nav),
|
||||
{str(block) for block in expected_nav},
|
||||
set(
|
||||
block_structure.get_transformer_block_field(
|
||||
block_key,
|
||||
@@ -114,7 +113,7 @@ class BlockNavigationTransformerCourseTestCase(ModuleStoreTestCase):
|
||||
course_key.make_usage_key('vertical', 'vertical_y1a'),
|
||||
course_key.make_usage_key('problem', 'problem_y1a_1'),
|
||||
]:
|
||||
assert six.text_type(block_key) in course_descendants
|
||||
assert str(block_key) in course_descendants
|
||||
|
||||
# chapter_x and its descendants should not be included
|
||||
for block_key in [
|
||||
@@ -123,4 +122,4 @@ class BlockNavigationTransformerCourseTestCase(ModuleStoreTestCase):
|
||||
course_key.make_usage_key('vertical', 'vertical_x1a'),
|
||||
course_key.make_usage_key('problem', 'problem_x1a_1'),
|
||||
]:
|
||||
assert six.text_type(block_key) not in course_descendants
|
||||
assert str(block_key) not in course_descendants
|
||||
|
||||
@@ -20,7 +20,7 @@ class TestStudentViewTransformer(ModuleStoreTestCase):
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestStudentViewTransformer, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course_key = ToyCourseFactory.create().id
|
||||
self.course_usage_key = self.store.make_course_usage_key(self.course_key)
|
||||
self.block_structure = BlockStructureFactory.create_from_modulestore(self.course_usage_key, self.store)
|
||||
|
||||
@@ -3,8 +3,7 @@ Tests for VideoBlockURLTransformer.
|
||||
"""
|
||||
|
||||
|
||||
import mock
|
||||
import six
|
||||
from unittest import mock
|
||||
|
||||
from openedx.core.djangoapps.content.block_structure.factory import BlockStructureFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
@@ -20,7 +19,7 @@ class TestVideoBlockURLTransformer(ModuleStoreTestCase):
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestVideoBlockURLTransformer, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course_key = ToyCourseFactory.create().id
|
||||
self.course_usage_key = self.store.make_course_usage_key(self.course_key)
|
||||
self.block_structure = BlockStructureFactory.create_from_modulestore(self.course_usage_key, self.store)
|
||||
@@ -37,7 +36,7 @@ class TestVideoBlockURLTransformer(ModuleStoreTestCase):
|
||||
Relocate url data in new dictionary for pre & post transformation data comparison.
|
||||
"""
|
||||
video_urls = {}
|
||||
for video_format, video_data in six.iteritems(encoded_videos):
|
||||
for video_format, video_data in encoded_videos.items():
|
||||
video_urls[video_format] = video_data['url']
|
||||
return video_urls
|
||||
|
||||
@@ -91,7 +90,7 @@ class TestVideoBlockURLTransformer(ModuleStoreTestCase):
|
||||
post_transform_data = self.get_post_transform_data(video_block_key)
|
||||
post_transform_data = self.change_encoded_videos_presentation(post_transform_data['encoded_videos'])
|
||||
|
||||
for video_format, video_url in six.iteritems(post_transform_data):
|
||||
for video_format, video_url in post_transform_data.items():
|
||||
assert pre_transform_data[video_format] != video_url
|
||||
|
||||
@mock.patch('xmodule.video_module.VideoBlock.student_view_data')
|
||||
@@ -121,7 +120,7 @@ class TestVideoBlockURLTransformer(ModuleStoreTestCase):
|
||||
post_transform_data = self.get_post_transform_data(video_block_key)
|
||||
post_transform_data = self.change_encoded_videos_presentation(post_transform_data['encoded_videos'])
|
||||
|
||||
for video_format, video_url in six.iteritems(post_transform_data):
|
||||
for video_format, video_url in post_transform_data.items():
|
||||
assert pre_transform_data[video_format] == video_url
|
||||
|
||||
@mock.patch('xmodule.video_module.VideoBlock.student_view_data')
|
||||
|
||||
@@ -3,11 +3,10 @@ Video block URL Transformer
|
||||
"""
|
||||
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
|
||||
from xmodule.video_module.video_utils import rewrite_video_url
|
||||
from openedx.core.djangoapps.content.block_structure.transformer import BlockStructureTransformer
|
||||
from xmodule.video_module.video_utils import rewrite_video_url
|
||||
|
||||
from .student_view import StudentViewTransformer
|
||||
|
||||
@@ -52,7 +51,7 @@ class VideoBlockURLTransformer(BlockStructureTransformer):
|
||||
if only_on_web:
|
||||
continue
|
||||
encoded_videos = student_view_data.get('encoded_videos')
|
||||
for video_format, video_data in six.iteritems(encoded_videos):
|
||||
for video_format, video_data in encoded_videos.items():
|
||||
if video_format in self.VIDEO_FORMAT_EXCEPTIONS:
|
||||
continue
|
||||
video_data['url'] = rewrite_video_url(self.CDN_URL, video_data['url'])
|
||||
|
||||
@@ -11,7 +11,7 @@ from .views import BlocksInCourseView, BlocksView
|
||||
urlpatterns = [
|
||||
# This endpoint requires the usage_key for the starting block.
|
||||
url(
|
||||
r'^v1/blocks/{}'.format(settings.USAGE_KEY_PATTERN),
|
||||
fr'^v1/blocks/{settings.USAGE_KEY_PATTERN}',
|
||||
BlocksView.as_view(),
|
||||
kwargs={'hide_access_denials': True},
|
||||
name="blocks_in_block_tree"
|
||||
@@ -26,7 +26,7 @@ urlpatterns = [
|
||||
),
|
||||
# This endpoint requires the usage_key for the starting block.
|
||||
url(
|
||||
r'^v2/blocks/{}'.format(settings.USAGE_KEY_PATTERN),
|
||||
fr'^v2/blocks/{settings.USAGE_KEY_PATTERN}',
|
||||
BlocksView.as_view(),
|
||||
name="blocks_in_block_tree"
|
||||
),
|
||||
|
||||
@@ -3,7 +3,6 @@ CourseBlocks API views
|
||||
"""
|
||||
|
||||
|
||||
import six
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import transaction
|
||||
from django.http import Http404
|
||||
@@ -13,7 +12,6 @@ from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from rest_framework.generics import ListAPIView
|
||||
from rest_framework.response import Response
|
||||
from six import text_type
|
||||
|
||||
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes
|
||||
from xmodule.modulestore.django import modulestore
|
||||
@@ -238,7 +236,7 @@ class BlocksView(DeveloperErrorViewMixin, ListAPIView):
|
||||
patch_response_headers(response)
|
||||
return response
|
||||
except ItemNotFoundError as exception:
|
||||
raise Http404(u"Block not found: {}".format(text_type(exception))) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise Http404("Block not found: {}".format(str(exception))) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
|
||||
@view_auth_classes(is_authenticated=False)
|
||||
@@ -301,9 +299,9 @@ class BlocksInCourseView(BlocksView):
|
||||
course_key = CourseKey.from_string(course_key_string)
|
||||
course_usage_key = modulestore().make_course_usage_key(course_key)
|
||||
except InvalidKeyError:
|
||||
raise ValidationError(u"'{}' is not a valid course key.".format(six.text_type(course_key_string))) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise ValidationError("'{}' is not a valid course key.".format(str(course_key_string))) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
response = super().list(request, course_usage_key,
|
||||
hide_access_denials=hide_access_denials) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
hide_access_denials=hide_access_denials)
|
||||
|
||||
calculate_completion = any('completion' in param
|
||||
for param in request.query_params.getlist('requested_fields', []))
|
||||
@@ -323,7 +321,7 @@ class BlocksInCourseView(BlocksView):
|
||||
course_blocks = response.data['blocks']
|
||||
|
||||
if not root:
|
||||
raise ValueError("Unable to find course block in {}".format(course_key_string))
|
||||
raise ValueError(f"Unable to find course block in {course_key_string}")
|
||||
|
||||
recurse_mark_complete(root, course_blocks)
|
||||
return response
|
||||
|
||||
@@ -5,7 +5,6 @@ Course API forms
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
import six
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms import CharField, Form
|
||||
from opaque_keys import InvalidKeyError
|
||||
@@ -14,7 +13,7 @@ from opaque_keys.edx.keys import CourseKey
|
||||
from openedx.core.djangoapps.util.forms import ExtendedNullBooleanField
|
||||
|
||||
|
||||
class UsernameValidatorMixin(object):
|
||||
class UsernameValidatorMixin:
|
||||
"""
|
||||
Mixin class for validating the username parameter.
|
||||
"""
|
||||
@@ -43,7 +42,7 @@ class CourseDetailGetForm(UsernameValidatorMixin, Form):
|
||||
try:
|
||||
return CourseKey.from_string(course_key_string)
|
||||
except InvalidKeyError:
|
||||
raise ValidationError(u"'{}' is not a valid course key.".format(six.text_type(course_key_string))) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise ValidationError("'{}' is not a valid course key.".format(str(course_key_string))) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
|
||||
class CourseListGetForm(UsernameValidatorMixin, Form):
|
||||
@@ -65,7 +64,7 @@ class CourseListGetForm(UsernameValidatorMixin, Form):
|
||||
"""
|
||||
Return cleaned data, including additional filters.
|
||||
"""
|
||||
cleaned_data = super(CourseListGetForm, self).clean() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
cleaned_data = super().clean()
|
||||
|
||||
# create a filter for all supported filter fields
|
||||
filter_ = dict()
|
||||
|
||||
@@ -3,11 +3,14 @@ Course API Serializers. Representing course catalog data
|
||||
"""
|
||||
|
||||
|
||||
from edx_django_utils import monitoring as monitoring_utils
|
||||
import six.moves.urllib.parse # lint-amnesty, pylint: disable=wrong-import-order
|
||||
import urllib
|
||||
|
||||
from django.urls import reverse
|
||||
from edx_django_utils import monitoring as monitoring_utils
|
||||
from rest_framework import serializers
|
||||
|
||||
from openedx.core.djangoapps.content.course_overviews.models import \
|
||||
CourseOverview # lint-amnesty, pylint: disable=unused-import
|
||||
from openedx.core.djangoapps.models.course_details import CourseDetails
|
||||
from openedx.core.lib.api.fields import AbsoluteURLField
|
||||
|
||||
@@ -18,7 +21,7 @@ class _MediaSerializer(serializers.Serializer): # pylint: disable=abstract-meth
|
||||
"""
|
||||
|
||||
def __init__(self, uri_attribute, *args, **kwargs):
|
||||
super(_MediaSerializer, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
self.uri_attribute = uri_attribute
|
||||
|
||||
uri = serializers.SerializerMethodField(source='*')
|
||||
@@ -128,7 +131,7 @@ class CourseSerializer(serializers.Serializer): # pylint: disable=abstract-meth
|
||||
"""
|
||||
base_url = '?'.join([
|
||||
reverse('blocks_in_course'),
|
||||
six.moves.urllib.parse.urlencode({'course_id': course_overview.id}),
|
||||
urllib.parse.urlencode({'course_id': course_overview.id}),
|
||||
])
|
||||
return self.context['request'].build_absolute_uri(base_url)
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ from datetime import datetime
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from xmodule.modulestore.tests.factories import ToyCourseFactory
|
||||
|
||||
TEST_PASSWORD = u'edx'
|
||||
TEST_PASSWORD = 'edx'
|
||||
|
||||
|
||||
class CourseApiFactoryMixin(object):
|
||||
class CourseApiFactoryMixin:
|
||||
"""
|
||||
Mixin to allow creation of test courses and users.
|
||||
"""
|
||||
@@ -37,7 +37,7 @@ class CourseApiFactoryMixin(object):
|
||||
"""
|
||||
return UserFactory(
|
||||
username=username,
|
||||
email=u'{}@example.com'.format(username),
|
||||
email=f'{username}@example.com',
|
||||
password=TEST_PASSWORD,
|
||||
is_staff=is_staff
|
||||
)
|
||||
|
||||
@@ -4,11 +4,11 @@ Test for course API
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from hashlib import md5
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.http import Http404
|
||||
import mock
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from rest_framework.request import Request
|
||||
@@ -30,11 +30,11 @@ class CourseApiTestMixin(CourseApiFactoryMixin):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(CourseApiTestMixin, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.request_factory = APIRequestFactory()
|
||||
CourseOverview.get_all_courses() # seed the CourseOverview table
|
||||
|
||||
def verify_course(self, course, course_id=u'edX/toy/2012_Fall'):
|
||||
def verify_course(self, course, course_id='edX/toy/2012_Fall'):
|
||||
"""
|
||||
Ensure that the returned course is the course we just created
|
||||
"""
|
||||
@@ -65,9 +65,9 @@ class TestGetCourseDetail(CourseDetailTestMixin, SharedModuleStoreTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestGetCourseDetail, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = cls.create_course()
|
||||
cls.hidden_course = cls.create_course(course=u'hidden', visible_to_staff_only=True)
|
||||
cls.hidden_course = cls.create_course(course='hidden', visible_to_staff_only=True)
|
||||
cls.honor_user = cls.create_user('honor', is_staff=False)
|
||||
cls.staff_user = cls.create_user('staff', is_staff=True)
|
||||
|
||||
@@ -76,7 +76,7 @@ class TestGetCourseDetail(CourseDetailTestMixin, SharedModuleStoreTestCase):
|
||||
self.verify_course(course)
|
||||
|
||||
def test_get_nonexistent_course(self):
|
||||
course_key = CourseKey.from_string(u'edX/toy/nope')
|
||||
course_key = CourseKey.from_string('edX/toy/nope')
|
||||
with pytest.raises(Http404):
|
||||
self._make_api_call(self.honor_user, self.honor_user, course_key)
|
||||
|
||||
@@ -86,7 +86,7 @@ class TestGetCourseDetail(CourseDetailTestMixin, SharedModuleStoreTestCase):
|
||||
|
||||
def test_hidden_course_for_staff(self):
|
||||
course = self._make_api_call(self.staff_user, self.staff_user, self.hidden_course.id)
|
||||
self.verify_course(course, course_id=u'edX/hidden/2012_Fall')
|
||||
self.verify_course(course, course_id='edX/hidden/2012_Fall')
|
||||
|
||||
def test_hidden_course_for_staff_as_honor(self):
|
||||
with pytest.raises(Http404):
|
||||
@@ -124,7 +124,7 @@ class TestGetCourseList(CourseListTestMixin, SharedModuleStoreTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestGetCourseList, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = cls.create_course()
|
||||
cls.staff_user = cls.create_user("staff", is_staff=True)
|
||||
cls.honor_user = cls.create_user("honor", is_staff=False)
|
||||
@@ -165,7 +165,7 @@ class TestGetCourseListMultipleCourses(CourseListTestMixin, ModuleStoreTestCase)
|
||||
ENABLED_SIGNALS = ['course_published']
|
||||
|
||||
def setUp(self):
|
||||
super(TestGetCourseListMultipleCourses, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = self.create_course(mobile_available=False)
|
||||
self.staff_user = self.create_user("staff", is_staff=True)
|
||||
self.honor_user = self.create_user("honor", is_staff=False)
|
||||
@@ -217,7 +217,7 @@ class TestGetCourseListExtras(CourseListTestMixin, ModuleStoreTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestGetCourseListExtras, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.staff_user = cls.create_user("staff", is_staff=True)
|
||||
cls.honor_user = cls.create_user("honor", is_staff=False)
|
||||
|
||||
|
||||
@@ -3,22 +3,21 @@ Tests for Course API forms.
|
||||
"""
|
||||
|
||||
from itertools import product
|
||||
from urllib.parse import urlencode
|
||||
|
||||
import ddt
|
||||
import six
|
||||
from six.moves.urllib.parse import urlencode
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.http import QueryDict
|
||||
|
||||
from openedx.core.djangoapps.util.test_forms import FormTestMixin
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from openedx.core.djangoapps.util.test_forms import FormTestMixin
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
from ..forms import CourseDetailGetForm, CourseIdListGetForm, CourseListGetForm
|
||||
|
||||
|
||||
class UsernameTestMixin(object):
|
||||
class UsernameTestMixin:
|
||||
"""
|
||||
Tests the username Form field.
|
||||
"""
|
||||
@@ -43,12 +42,12 @@ class TestCourseListGetForm(FormTestMixin, UsernameTestMixin, SharedModuleStoreT
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestCourseListGetForm, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
def setUp(self):
|
||||
super(TestCourseListGetForm, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.student = UserFactory.create()
|
||||
self.set_up_data(self.student)
|
||||
@@ -105,12 +104,12 @@ class TestCourseIdListGetForm(FormTestMixin, UsernameTestMixin, SharedModuleStor
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestCourseIdListGetForm, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
def setUp(self):
|
||||
super(TestCourseIdListGetForm, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.student = UserFactory.create()
|
||||
self.set_up_data(self.student)
|
||||
@@ -144,12 +143,12 @@ class TestCourseDetailGetForm(FormTestMixin, UsernameTestMixin, SharedModuleStor
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestCourseDetailGetForm, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
def setUp(self):
|
||||
super(TestCourseDetailGetForm, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.student = UserFactory.create()
|
||||
self.set_up_data(self.student)
|
||||
@@ -162,7 +161,7 @@ class TestCourseDetailGetForm(FormTestMixin, UsernameTestMixin, SharedModuleStor
|
||||
self.form_data = QueryDict(
|
||||
urlencode({
|
||||
'username': user.username,
|
||||
'course_key': six.text_type(self.course.id),
|
||||
'course_key': str(self.course.id),
|
||||
}),
|
||||
mutable=True,
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ class ViewCoursesForUsernameTestCase(CourseApiFactoryMixin, TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(ViewCoursesForUsernameTestCase, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.staff_user = cls.create_user('staff', is_staff=True)
|
||||
cls.honor_user = cls.create_user('honor', is_staff=False)
|
||||
cls.anonymous_user = AnonymousUser()
|
||||
|
||||
@@ -7,10 +7,10 @@ from datetime import datetime
|
||||
from unittest import TestCase
|
||||
|
||||
import ddt
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.test import APIRequestFactory
|
||||
from xblock.core import XBlock
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.models.course_details import CourseDetails
|
||||
@@ -34,22 +34,22 @@ class TestCourseSerializer(CourseApiFactoryMixin, ModuleStoreTestCase):
|
||||
ENABLED_SIGNALS = ['course_published']
|
||||
|
||||
def setUp(self):
|
||||
super(TestCourseSerializer, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.staff_user = self.create_user('staff', is_staff=True)
|
||||
self.honor_user = self.create_user('honor', is_staff=False)
|
||||
self.request_factory = APIRequestFactory()
|
||||
|
||||
course_id = u'edX/toy/2012_Fall'
|
||||
banner_image_uri = u'/c4x/edX/toy/asset/images_course_image.jpg'
|
||||
banner_image_absolute_uri = u'http://testserver' + banner_image_uri
|
||||
image_path = u'/c4x/edX/toy/asset/just_a_test.jpg'
|
||||
image_url = u'http://testserver' + image_path
|
||||
course_id = 'edX/toy/2012_Fall'
|
||||
banner_image_uri = '/c4x/edX/toy/asset/images_course_image.jpg'
|
||||
banner_image_absolute_uri = 'http://testserver' + banner_image_uri
|
||||
image_path = '/c4x/edX/toy/asset/just_a_test.jpg'
|
||||
image_url = 'http://testserver' + image_path
|
||||
self.expected_data = {
|
||||
'id': course_id,
|
||||
'name': u'Toy Course',
|
||||
'number': u'toy',
|
||||
'org': u'edX',
|
||||
'short_description': u'A course about toys.',
|
||||
'name': 'Toy Course',
|
||||
'number': 'toy',
|
||||
'org': 'edX',
|
||||
'short_description': 'A course about toys.',
|
||||
'media': {
|
||||
'banner_image': {
|
||||
'uri': banner_image_uri,
|
||||
@@ -59,7 +59,7 @@ class TestCourseSerializer(CourseApiFactoryMixin, ModuleStoreTestCase):
|
||||
'uri': image_path,
|
||||
},
|
||||
'course_video': {
|
||||
'uri': u'http://www.youtube.com/watch?v=test_youtube_id',
|
||||
'uri': 'http://www.youtube.com/watch?v=test_youtube_id',
|
||||
},
|
||||
'image': {
|
||||
'raw': image_url,
|
||||
@@ -67,14 +67,14 @@ class TestCourseSerializer(CourseApiFactoryMixin, ModuleStoreTestCase):
|
||||
'large': image_url,
|
||||
}
|
||||
},
|
||||
'start': u'2015-07-17T12:00:00Z',
|
||||
'start_type': u'timestamp',
|
||||
'start_display': u'July 17, 2015',
|
||||
'end': u'2015-09-19T18:00:00Z',
|
||||
'enrollment_start': u'2015-06-15T00:00:00Z',
|
||||
'enrollment_end': u'2015-07-15T00:00:00Z',
|
||||
'blocks_url': u'http://testserver/api/courses/v2/blocks/?course_id=edX%2Ftoy%2F2012_Fall',
|
||||
'effort': u'6 hours',
|
||||
'start': '2015-07-17T12:00:00Z',
|
||||
'start_type': 'timestamp',
|
||||
'start_display': 'July 17, 2015',
|
||||
'end': '2015-09-19T18:00:00Z',
|
||||
'enrollment_start': '2015-06-15T00:00:00Z',
|
||||
'enrollment_end': '2015-07-15T00:00:00Z',
|
||||
'blocks_url': 'http://testserver/api/courses/v2/blocks/?course_id=edX%2Ftoy%2F2012_Fall',
|
||||
'effort': '6 hours',
|
||||
'pacing': 'instructor',
|
||||
'mobile_available': True,
|
||||
'hidden': False,
|
||||
@@ -110,29 +110,29 @@ class TestCourseSerializer(CourseApiFactoryMixin, ModuleStoreTestCase):
|
||||
|
||||
def test_hidden(self):
|
||||
course = self.create_course(
|
||||
course=u'custom',
|
||||
course='custom',
|
||||
start=datetime(2015, 3, 15),
|
||||
catalog_visibility=u'none'
|
||||
catalog_visibility='none'
|
||||
)
|
||||
result = self._get_result(course)
|
||||
assert result['hidden'] is True
|
||||
|
||||
def test_advertised_start(self):
|
||||
course = self.create_course(
|
||||
course=u'custom',
|
||||
course='custom',
|
||||
start=datetime(2015, 3, 15),
|
||||
advertised_start=u'The Ides of March'
|
||||
advertised_start='The Ides of March'
|
||||
)
|
||||
result = self._get_result(course)
|
||||
assert result['course_id'] == u'edX/custom/2012_Fall'
|
||||
assert result['start_type'] == u'string'
|
||||
assert result['start_display'] == u'The Ides of March'
|
||||
assert result['course_id'] == 'edX/custom/2012_Fall'
|
||||
assert result['start_type'] == 'string'
|
||||
assert result['start_display'] == 'The Ides of March'
|
||||
|
||||
def test_empty_start(self):
|
||||
course = self.create_course(start=DEFAULT_START_DATE, course=u'custom')
|
||||
course = self.create_course(start=DEFAULT_START_DATE, course='custom')
|
||||
result = self._get_result(course)
|
||||
assert result['course_id'] == u'edX/custom/2012_Fall'
|
||||
assert result['start_type'] == u'empty'
|
||||
assert result['course_id'] == 'edX/custom/2012_Fall'
|
||||
assert result['start_type'] == 'empty'
|
||||
assert result['start_display'] is None
|
||||
|
||||
@ddt.unpack
|
||||
@@ -158,7 +158,7 @@ class TestCourseDetailSerializer(TestCourseSerializer): # lint-amnesty, pylint:
|
||||
serializer_class = CourseDetailSerializer
|
||||
|
||||
def setUp(self):
|
||||
super(TestCourseDetailSerializer, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
# update the expected_data to include the 'overview' data.
|
||||
about_descriptor = XBlock.load_class('about')
|
||||
|
||||
@@ -7,13 +7,12 @@ from hashlib import md5
|
||||
from unittest import TestCase
|
||||
import pytest
|
||||
import ddt
|
||||
import six
|
||||
from six.moves import range
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.test import RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from edx_django_utils.cache import RequestCache
|
||||
from opaque_keys.edx.locator import LibraryLocator
|
||||
from search.tests.test_course_discovery import DemoCourse
|
||||
from search.tests.tests import TEST_INDEX_NAME
|
||||
from search.tests.utils import SearcherMixin
|
||||
@@ -21,13 +20,12 @@ from waffle.testutils import override_switch
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
from opaque_keys.edx.locator import LibraryLocator # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from openedx.core.lib.api.view_utils import LazySequence
|
||||
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
|
||||
from openedx.features.course_duration_limits.models import CourseDurationLimitConfig
|
||||
from common.djangoapps.student.auth import add_users
|
||||
from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRole
|
||||
from common.djangoapps.student.tests.factories import AdminFactory
|
||||
from openedx.core.lib.api.view_utils import LazySequence
|
||||
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
|
||||
from openedx.features.course_duration_limits.models import CourseDurationLimitConfig
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
@@ -78,7 +76,7 @@ class CourseListViewTestCase(CourseApiTestViewMixin, SharedModuleStoreTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(CourseListViewTestCase, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = cls.create_course()
|
||||
cls.url = reverse('course-list')
|
||||
cls.staff_user = cls.create_user(username='staff', is_staff=True)
|
||||
@@ -159,7 +157,7 @@ class CourseListViewTestCaseMultipleCourses(CourseApiTestViewMixin, ModuleStoreT
|
||||
ENABLED_SIGNALS = ['course_published']
|
||||
|
||||
def setUp(self):
|
||||
super(CourseListViewTestCaseMultipleCourses, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = self.create_course(mobile_available=False)
|
||||
self.url = reverse('course-list')
|
||||
self.staff_user = self.create_user(username='staff', is_staff=True)
|
||||
@@ -201,7 +199,7 @@ class CourseListViewTestCaseMultipleCourses(CourseApiTestViewMixin, ModuleStoreT
|
||||
if filter_:
|
||||
params.update(filter_)
|
||||
response = self.verify_response(params=params)
|
||||
assert {course['course_id'] for course in response.data['results']} == {six.text_type(course.id) for course in expected_courses}, f'testing course_api.views.CourseListView with filter_={filter_}' # pylint: disable=line-too-long
|
||||
assert {course['course_id'] for course in response.data['results']} == {str(course.id) for course in expected_courses}, f'testing course_api.views.CourseListView with filter_={filter_}' # pylint: disable=line-too-long
|
||||
|
||||
|
||||
class CourseDetailViewTestCase(CourseApiTestViewMixin, SharedModuleStoreTestCase):
|
||||
@@ -211,9 +209,9 @@ class CourseDetailViewTestCase(CourseApiTestViewMixin, SharedModuleStoreTestCase
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(CourseDetailViewTestCase, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = cls.create_course()
|
||||
cls.hidden_course = cls.create_course(course=u'hidden', visible_to_staff_only=True)
|
||||
cls.hidden_course = cls.create_course(course='hidden', visible_to_staff_only=True)
|
||||
cls.url = reverse('course-detail', kwargs={'course_key_string': cls.course.id})
|
||||
cls.hidden_url = reverse('course-detail', kwargs={'course_key_string': cls.hidden_course.id})
|
||||
cls.nonexistent_url = reverse('course-detail', kwargs={'course_key_string': 'edX/nope/Fall_2014'})
|
||||
@@ -289,7 +287,7 @@ class CourseListSearchViewTest(CourseApiTestViewMixin, ModuleStoreTestCase, Sear
|
||||
ENABLED_CACHES = ModuleStoreTestCase.ENABLED_CACHES + ['configuration']
|
||||
|
||||
def setUp(self):
|
||||
super(CourseListSearchViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
DemoCourse.reset_count()
|
||||
self.searcher.destroy()
|
||||
|
||||
@@ -316,7 +314,7 @@ class CourseListSearchViewTest(CourseApiTestViewMixin, ModuleStoreTestCase, Sear
|
||||
'run': '2010',
|
||||
'number': 'DemoZ',
|
||||
# Using the slash separated course ID bcuz `DemoCourse` isn't updated yet to new locator.
|
||||
'id': '{org_code}/DemoZ/2010'.format(org_code=org_code),
|
||||
'id': f'{org_code}/DemoZ/2010',
|
||||
'content': {
|
||||
'short_description': short_description,
|
||||
},
|
||||
@@ -377,10 +375,10 @@ class CourseListSearchViewTest(CourseApiTestViewMixin, ModuleStoreTestCase, Sear
|
||||
|
||||
# Create 300 courses across 30 organizations
|
||||
for org_num in range(10):
|
||||
org_id = 'org{}'.format(org_num)
|
||||
org_id = f'org{org_num}'
|
||||
for course_num in range(30):
|
||||
course_name = 'course{}.{}'.format(org_num, course_num)
|
||||
course_run_name = 'run{}.{}'.format(org_num, course_num)
|
||||
course_name = f'course{org_num}.{course_num}'
|
||||
course_run_name = f'run{org_num}.{course_num}'
|
||||
course = CourseFactory.create(org=org_id, number=course_name, run=course_run_name, emit_signals=True)
|
||||
CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.AUDIT)
|
||||
CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.VERIFIED)
|
||||
@@ -412,7 +410,7 @@ class CourseIdListViewTestCase(CourseApiTestViewMixin, ModuleStoreTestCase):
|
||||
ENABLED_SIGNALS = ['course_published']
|
||||
|
||||
def setUp(self):
|
||||
super(CourseIdListViewTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = self.create_course()
|
||||
self.url = reverse('course-id-list')
|
||||
self.staff_user = self.create_user(username='staff', is_staff=True)
|
||||
@@ -528,7 +526,7 @@ class CourseIdListViewTestCase(CourseApiTestViewMixin, ModuleStoreTestCase):
|
||||
class LazyPageNumberPaginationTestCase(TestCase): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
|
||||
def test_lazy_page_number_pagination(self):
|
||||
number_sequence = range(20)
|
||||
number_sequence = range(20) # lint-amnesty, pylint: disable=range-builtin-not-iterating
|
||||
even_numbers_lazy_sequence = LazySequence(
|
||||
(
|
||||
number for number in number_sequence
|
||||
@@ -557,7 +555,7 @@ class LazyPageNumberPaginationTestCase(TestCase): # lint-amnesty, pylint: disab
|
||||
self.assertDictEqual(expected_response, paginated_response.data)
|
||||
|
||||
def test_not_found_error_for_invalid_page(self):
|
||||
number_sequence = range(20)
|
||||
number_sequence = range(20) # lint-amnesty, pylint: disable=range-builtin-not-iterating
|
||||
even_numbers_lazy_sequence = LazySequence(
|
||||
(
|
||||
number for number in number_sequence
|
||||
|
||||
@@ -10,7 +10,7 @@ from .views import CourseDetailView, CourseIdListView, CourseListView
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^v1/courses/$', CourseListView.as_view(), name="course-list"),
|
||||
url(r'^v1/courses/{}'.format(settings.COURSE_KEY_PATTERN), CourseDetailView.as_view(), name="course-detail"),
|
||||
url(fr'^v1/courses/{settings.COURSE_KEY_PATTERN}', CourseDetailView.as_view(), name="course-detail"),
|
||||
url(r'^v1/course_ids/$', CourseIdListView.as_view(), name="course-id-list"),
|
||||
url(r'', include('lms.djangoapps.course_api.blocks.urls'))
|
||||
]
|
||||
|
||||
@@ -7,9 +7,9 @@ from django.core.exceptions import ValidationError
|
||||
from django.core.paginator import InvalidPage
|
||||
from edx_django_utils.monitoring import function_trace
|
||||
from edx_rest_framework_extensions.paginators import NamespacedPageNumberPagination
|
||||
from rest_framework.exceptions import NotFound
|
||||
from rest_framework.generics import ListAPIView, RetrieveAPIView
|
||||
from rest_framework.throttling import UserRateThrottle
|
||||
from rest_framework.exceptions import NotFound
|
||||
|
||||
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes
|
||||
|
||||
@@ -159,7 +159,7 @@ class CourseListUserThrottle(UserRateThrottle):
|
||||
self.rate = self.get_rate()
|
||||
self.num_requests, self.duration = self.parse_rate(self.rate)
|
||||
|
||||
return super(CourseListUserThrottle, self).allow_request(request, view) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().allow_request(request, view)
|
||||
|
||||
|
||||
class LazyPageNumberPagination(NamespacedPageNumberPagination):
|
||||
@@ -193,7 +193,7 @@ class LazyPageNumberPagination(NamespacedPageNumberPagination):
|
||||
self.page.number = self.page.paginator.num_pages
|
||||
raise NotFound(msg) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
return super(LazyPageNumberPagination, self).get_paginated_response(data) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().get_paginated_response(data)
|
||||
|
||||
@function_trace('pagination_paginate_queryset')
|
||||
def paginate_queryset(self, queryset, request, view=None):
|
||||
@@ -347,7 +347,7 @@ class CourseIdListUserThrottle(UserRateThrottle):
|
||||
self.rate = self.get_rate()
|
||||
self.num_requests, self.duration = self.parse_rate(self.rate)
|
||||
|
||||
return super(CourseIdListUserThrottle, self).allow_request(request, view) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().allow_request(request, view)
|
||||
|
||||
|
||||
@view_auth_classes()
|
||||
@@ -434,7 +434,7 @@ class CourseIdListView(DeveloperErrorViewMixin, ListAPIView):
|
||||
|
||||
This should be called once per GET request.
|
||||
"""
|
||||
return super(CourseIdListView, self).paginate_queryset(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().paginate_queryset(*args, **kwargs)
|
||||
|
||||
@function_trace('get_paginated_response')
|
||||
def get_paginated_response(self, *args, **kwargs):
|
||||
@@ -446,7 +446,7 @@ class CourseIdListView(DeveloperErrorViewMixin, ListAPIView):
|
||||
means two GET requests and one function call per request. Otherwise, if
|
||||
the whole response fits in one page, this function never gets called.
|
||||
"""
|
||||
return super(CourseIdListView, self).get_paginated_response(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().get_paginated_response(*args, **kwargs)
|
||||
|
||||
@function_trace('filter_queryset')
|
||||
def filter_queryset(self, *args, **kwargs):
|
||||
@@ -456,7 +456,7 @@ class CourseIdListView(DeveloperErrorViewMixin, ListAPIView):
|
||||
|
||||
This should be called once per GET request.
|
||||
"""
|
||||
return super(CourseIdListView, self).filter_queryset(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().filter_queryset(*args, **kwargs)
|
||||
|
||||
@function_trace('get_serializer')
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
@@ -466,4 +466,4 @@ class CourseIdListView(DeveloperErrorViewMixin, ListAPIView):
|
||||
|
||||
This should be called once per GET request.
|
||||
"""
|
||||
return super(CourseIdListView, self).get_serializer(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().get_serializer(*args, **kwargs)
|
||||
|
||||
Reference in New Issue
Block a user