Commit 4805946a by Peter Fogg

Override due dates in the LMS for self-paced courses.

parent 7f673604
......@@ -9,6 +9,7 @@ from nose.plugins.attrib import attr
from courseware.field_overrides import OverrideFieldData # pylint: disable=import-error
from django.test.utils import override_settings
from lms.djangoapps.courseware.tests.test_field_overrides import inject_field_overrides
from request_cache.middleware import RequestCache
from student.tests.factories import AdminFactory # pylint: disable=import-error
from xmodule.modulestore.tests.django_utils import (
......@@ -69,13 +70,7 @@ class TestFieldOverrides(ModuleStoreTestCase):
self.addCleanup(RequestCache.clear_request_cache)
# Apparently the test harness doesn't use LmsFieldStorage, and I'm not
# sure if there's a way to poke the test harness to do so. So, we'll
# just inject the override field storage in this brute force manner.
OverrideFieldData.provider_classes = None
for block in iter_blocks(ccx.course):
block._field_data = OverrideFieldData.wrap( # pylint: disable=protected-access
AdminFactory.create(), course, block._field_data) # pylint: disable=protected-access
inject_field_overrides(iter_blocks(ccx.course), course, AdminFactory.create())
def cleanup_provider_classes():
"""
......
......@@ -24,7 +24,7 @@ from xblock.field_data import FieldData
from xmodule.modulestore.inheritance import InheritanceMixin
NOTSET = object()
ENABLED_OVERRIDE_PROVIDERS_KEY = "courseware.field_overrides.enabled_providers"
ENABLED_OVERRIDE_PROVIDERS_KEY = "courseware.field_overrides.enabled_providers.{course_id}"
def resolve_dotted(name):
......@@ -77,7 +77,6 @@ class OverrideFieldData(FieldData):
settings.FIELD_OVERRIDE_PROVIDERS))
enabled_providers = cls._providers_for_course(course)
if enabled_providers:
# TODO: we might not actually want to return here. Might be better
# to check for instance.providers after the instance is built. This
......@@ -98,14 +97,16 @@ class OverrideFieldData(FieldData):
course: The course XBlock
"""
request_cache = RequestCache.get_request_cache()
enabled_providers = request_cache.data.get(
ENABLED_OVERRIDE_PROVIDERS_KEY, NOTSET
)
if course is None:
cache_key = ENABLED_OVERRIDE_PROVIDERS_KEY.format(course_id='None')
else:
cache_key = ENABLED_OVERRIDE_PROVIDERS_KEY.format(course_id=unicode(course.id))
enabled_providers = request_cache.data.get(cache_key, NOTSET)
if enabled_providers == NOTSET:
enabled_providers = tuple(
(provider_class for provider_class in cls.provider_classes if provider_class.enabled_for(course))
)
request_cache.data[ENABLED_OVERRIDE_PROVIDERS_KEY] = enabled_providers
request_cache.data[cache_key] = enabled_providers
return enabled_providers
......
"""
Field overrides for self-paced courses. This allows overriding due
dates for each block in the course.
"""
from .field_overrides import FieldOverrideProvider
class SelfPacedDateOverrideProvider(FieldOverrideProvider):
"""
A concrete implementation of
:class:`~courseware.field_overrides.FieldOverrideProvider` which allows for
due dates to be overridden for self-paced courses.
"""
def get(self, block, name, default):
if name == 'due':
return None
return default
@classmethod
def enabled_for(cls, course):
"""This provider is enabled for self-paced courses only."""
return course.self_paced
......@@ -132,3 +132,16 @@ class TestOverrideProvider(FieldOverrideProvider):
@classmethod
def enabled_for(cls, course):
return True
def inject_field_overrides(blocks, course, user):
"""
Apparently the test harness doesn't use LmsFieldStorage, and I'm
not sure if there's a way to poke the test harness to do so. So,
we'll just inject the override field storage in this brute force
manner.
"""
OverrideFieldData.provider_classes = None
for block in blocks:
block._field_data = OverrideFieldData.wrap( # pylint: disable=protected-access
user, course, block._field_data) # pylint: disable=protected-access
"""
Tests for self-paced course due date overrides.
"""
from datetime import datetime
from dateutil.tz import tzutc
from django.test.utils import override_settings
from student.tests.factories import UserFactory
from lms.djangoapps.ccx.tests.test_overrides import inject_field_overrides
from lms.djangoapps.courseware.field_overrides import OverrideFieldData
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
@override_settings(
FIELD_OVERRIDE_PROVIDERS=('courseware.self_paced_overrides.SelfPacedDateOverrideProvider',)
)
class SelfPacedDateOverrideTest(ModuleStoreTestCase):
"""
Tests for self-paced due date overrides.
"""
def setUp(self):
super(SelfPacedDateOverrideTest, self).setUp()
self.due_date = datetime(2015, 5, 26, 8, 30, 00).replace(tzinfo=tzutc())
self.instructor_led_course, self.il_section = self.setup_course("Instructor Led Course", False)
self.self_paced_course, self.sp_section = self.setup_course("Self-Paced Course", True)
def tearDown(self):
super(SelfPacedDateOverrideTest, self).tearDown()
OverrideFieldData.provider_classes = None
def setup_course(self, display_name, self_paced):
"""Set up a course with `display_name` and `self_paced` attributes.
Creates a child block with a due date, and ensures that field
overrides are correctly applied for both blocks.
"""
course = CourseFactory.create(display_name=display_name, self_paced=self_paced)
section = ItemFactory.create(parent=course, due=self.due_date)
inject_field_overrides((course, section), course, UserFactory.create())
return (course, section)
def test_instructor_led(self):
self.assertEqual(self.due_date, self.il_section.due)
def test_self_paced(self):
self.assertIsNone(self.sp_section.due)
......@@ -12,6 +12,7 @@ from django.test.utils import override_settings
from nose.plugins.attrib import attr
from courseware.field_overrides import OverrideFieldData # pylint: disable=import-error
from lms.djangoapps.ccx.tests.test_overrides import inject_field_overrides
from student.tests.factories import UserFactory # pylint: disable=import-error
from xmodule.fields import Date
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase
......@@ -196,7 +197,6 @@ class TestSetDueDateExtension(ModuleStoreTestCase):
Fixtures.
"""
super(TestSetDueDateExtension, self).setUp()
OverrideFieldData.provider_classes = None
self.due = due = datetime.datetime(2010, 5, 12, 2, 42, tzinfo=utc)
course = CourseFactory.create()
......@@ -216,12 +216,7 @@ class TestSetDueDateExtension(ModuleStoreTestCase):
self.week3 = week3
self.user = user
# Apparently the test harness doesn't use LmsFieldStorage, and I'm not
# sure if there's a way to poke the test harness to do so. So, we'll
# just inject the override field storage in this brute force manner.
for block in (course, week1, week2, week3, homework, assignment):
block._field_data = OverrideFieldData.wrap( # pylint: disable=protected-access
user, course, block._field_data) # pylint: disable=protected-access
inject_field_overrides((course, week1, week2, week3, homework, assignment), course, user)
def tearDown(self):
super(TestSetDueDateExtension, self).tearDown()
......
......@@ -676,6 +676,12 @@ if FEATURES.get('INDIVIDUAL_DUE_DATES'):
'courseware.student_field_overrides.IndividualStudentOverrideProvider',
)
##### Self-Paced Course Due Dates #####
if FEATURES.get('ENABLE_SELF_PACED_COURSES'):
FIELD_OVERRIDE_PROVIDERS += (
'courseware.self_paced_overrides.SelfPacedDateOverrideProvider',
)
# PROFILE IMAGE CONFIG
PROFILE_IMAGE_BACKEND = ENV_TOKENS.get('PROFILE_IMAGE_BACKEND', PROFILE_IMAGE_BACKEND)
PROFILE_IMAGE_SECRET_KEY = AUTH_TOKENS.get('PROFILE_IMAGE_SECRET_KEY', PROFILE_IMAGE_SECRET_KEY)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment