Schedules/ACE - support debug logging via waffle
This commit is contained in:
@@ -807,7 +807,7 @@ class CertificatesViewsTests(CommonCertificatesTestCase):
|
||||
as the issued date for instructor-paced courses
|
||||
"""
|
||||
self.course.self_paced = self_paced
|
||||
today = datetime.datetime.today()
|
||||
today = datetime.datetime.utcnow()
|
||||
self.course.certificate_available_date = today + datetime.timedelta(cert_avail_delta)
|
||||
self.store.update_item(self.course, self.user.id)
|
||||
self._add_course_certificates(count=1, signatory_count=1, is_active=True)
|
||||
|
||||
@@ -26,7 +26,7 @@ from courseware.models import DynamicUpgradeDeadlineConfiguration, CourseDynamic
|
||||
from lms.djangoapps.verify_student.models import VerificationDeadline
|
||||
from lms.djangoapps.verify_student.tests.factories import SoftwareSecurePhotoVerificationFactory
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.schedules.signals import SCHEDULE_WAFFLE_FLAG
|
||||
from openedx.core.djangoapps.schedules.signals import CREATE_SCHEDULE_WAFFLE_FLAG
|
||||
from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
|
||||
from openedx.core.djangoapps.user_api.preferences.api import set_user_preference
|
||||
@@ -481,7 +481,7 @@ class TestScheduleOverrides(SharedModuleStoreTestCase):
|
||||
|
||||
mock_get_current_site.return_value = SiteFactory.create()
|
||||
|
||||
@override_waffle_flag(SCHEDULE_WAFFLE_FLAG, True)
|
||||
@override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, True)
|
||||
def test_date_with_self_paced_with_enrollment_before_course_start(self):
|
||||
""" Enrolling before a course begins should result in the upgrade deadline being set relative to the
|
||||
course start date. """
|
||||
@@ -493,7 +493,7 @@ class TestScheduleOverrides(SharedModuleStoreTestCase):
|
||||
block = VerifiedUpgradeDeadlineDate(course, enrollment.user)
|
||||
self.assertEqual(block.date, expected)
|
||||
|
||||
@override_waffle_flag(SCHEDULE_WAFFLE_FLAG, True)
|
||||
@override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, True)
|
||||
def test_date_with_self_paced_with_enrollment_after_course_start(self):
|
||||
""" Enrolling after a course begins should result in the upgrade deadline being set relative to the
|
||||
enrollment date. """
|
||||
@@ -513,7 +513,7 @@ class TestScheduleOverrides(SharedModuleStoreTestCase):
|
||||
expected = enrollment.created + timedelta(days=course_config.deadline_days)
|
||||
self.assertEqual(block.date, expected)
|
||||
|
||||
@override_waffle_flag(SCHEDULE_WAFFLE_FLAG, True)
|
||||
@override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, True)
|
||||
def test_date_with_self_paced_without_dynamic_upgrade_deadline(self):
|
||||
""" Disabling the dynamic upgrade deadline functionality should result in the verified mode's
|
||||
expiration date being returned. """
|
||||
@@ -524,7 +524,7 @@ class TestScheduleOverrides(SharedModuleStoreTestCase):
|
||||
block = VerifiedUpgradeDeadlineDate(course, enrollment.user)
|
||||
self.assertEqual(block.date, expected)
|
||||
|
||||
@override_waffle_flag(SCHEDULE_WAFFLE_FLAG, True)
|
||||
@override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, True)
|
||||
def test_date_with_self_paced_with_single_course(self):
|
||||
""" If the global switch is off, a single course can still be enabled. """
|
||||
course = create_self_paced_course_run(days_till_start=-1)
|
||||
@@ -536,7 +536,7 @@ class TestScheduleOverrides(SharedModuleStoreTestCase):
|
||||
expected = enrollment.created + timedelta(days=course_config.deadline_days)
|
||||
self.assertEqual(block.date, expected)
|
||||
|
||||
@override_waffle_flag(SCHEDULE_WAFFLE_FLAG, True)
|
||||
@override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, True)
|
||||
def test_date_with_existing_schedule(self):
|
||||
""" If a schedule is created while deadlines are disabled, they shouldn't magically appear once the feature is
|
||||
turned on. """
|
||||
|
||||
12
openedx/core/djangoapps/schedules/config.py
Normal file
12
openedx/core/djangoapps/schedules/config.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleFlagNamespace, CourseWaffleFlag, WaffleFlag
|
||||
|
||||
|
||||
WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name=u'schedules')
|
||||
|
||||
CREATE_SCHEDULE_WAFFLE_FLAG = CourseWaffleFlag(
|
||||
waffle_namespace=WAFFLE_FLAG_NAMESPACE,
|
||||
flag_name=u'create_schedules_for_course',
|
||||
flag_undefined_default=False
|
||||
)
|
||||
|
||||
DEBUG_MESSAGE_WAFFLE_FLAG = WaffleFlag(WAFFLE_FLAG_NAMESPACE, u'enable_debugging')
|
||||
@@ -4,17 +4,15 @@ import datetime
|
||||
|
||||
from dateutil.tz import tzutc, gettz
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.test.utils import CaptureQueriesContext
|
||||
from django.db.models import Prefetch
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import DEFAULT_DB_ALIAS, connections
|
||||
from django.utils.http import urlquote
|
||||
|
||||
from openedx.core.djangoapps.schedules.message_type import ScheduleMessageType
|
||||
from openedx.core.djangoapps.schedules.models import Schedule
|
||||
from openedx.core.djangoapps.user_api.models import UserPreference
|
||||
|
||||
from edx_ace.message import MessageType
|
||||
from edx_ace.recipient_resolver import RecipientResolver
|
||||
from edx_ace import ace
|
||||
from edx_ace.recipient import Recipient
|
||||
@@ -24,7 +22,7 @@ from course_modes.models import CourseMode, format_course_price
|
||||
from lms.djangoapps.experiments.utils import check_and_get_upgrade_link
|
||||
|
||||
|
||||
class VerifiedUpgradeDeadlineReminder(MessageType):
|
||||
class VerifiedUpgradeDeadlineReminder(ScheduleMessageType):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ class TestSendRecurringNudge(CacheIsolationTestCase):
|
||||
# pylint: disable=protected-access
|
||||
|
||||
def setUp(self):
|
||||
super(TestSendRecurringNudge, self).setUp()
|
||||
|
||||
ScheduleFactory.create(start=datetime.datetime(2017, 8, 1, 15, 44, 30, tzinfo=pytz.UTC))
|
||||
ScheduleFactory.create(start=datetime.datetime(2017, 8, 1, 17, 34, 30, tzinfo=pytz.UTC))
|
||||
ScheduleFactory.create(start=datetime.datetime(2017, 8, 2, 15, 34, 30, tzinfo=pytz.UTC))
|
||||
@@ -74,7 +76,7 @@ class TestSendRecurringNudge(CacheIsolationTestCase):
|
||||
]
|
||||
|
||||
test_time_str = serialize(datetime.datetime(2017, 8, 1, 18, tzinfo=pytz.UTC))
|
||||
with self.assertNumQueries(1):
|
||||
with self.assertNumQueries(2):
|
||||
tasks.recurring_nudge_schedule_hour(
|
||||
self.site_config.site.id, 3, test_time_str, [schedules[0].enrollment.course.org],
|
||||
)
|
||||
@@ -91,7 +93,7 @@ class TestSendRecurringNudge(CacheIsolationTestCase):
|
||||
schedule.enrollment.save()
|
||||
|
||||
test_time_str = serialize(datetime.datetime(2017, 8, 1, 20, tzinfo=pytz.UTC))
|
||||
with self.assertNumQueries(1):
|
||||
with self.assertNumQueries(2):
|
||||
tasks.recurring_nudge_schedule_hour(
|
||||
self.site_config.site.id, 3, test_time_str, [schedule.enrollment.course.org],
|
||||
)
|
||||
@@ -152,7 +154,7 @@ class TestSendRecurringNudge(CacheIsolationTestCase):
|
||||
)
|
||||
|
||||
test_time_str = serialize(datetime.datetime(2017, 8, 2, 17, tzinfo=pytz.UTC))
|
||||
with self.assertNumQueries(1):
|
||||
with self.assertNumQueries(2):
|
||||
tasks.recurring_nudge_schedule_hour(
|
||||
limited_config.site.id, 3, test_time_str, org_list=org_list, exclude_orgs=exclude_orgs,
|
||||
)
|
||||
@@ -180,7 +182,7 @@ class TestSendRecurringNudge(CacheIsolationTestCase):
|
||||
]
|
||||
|
||||
test_time_str = serialize(datetime.datetime(2017, 8, 1, test_hour, tzinfo=pytz.UTC))
|
||||
with self.assertNumQueries(1):
|
||||
with self.assertNumQueries(2):
|
||||
tasks.recurring_nudge_schedule_hour(
|
||||
self.site_config.site.id, 3, test_time_str, [schedules[0].enrollment.course.org],
|
||||
)
|
||||
@@ -217,7 +219,7 @@ class TestSendRecurringNudge(CacheIsolationTestCase):
|
||||
with patch.object(tasks, '_recurring_nudge_schedule_send') as mock_schedule_send:
|
||||
mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(args)
|
||||
|
||||
with self.assertNumQueries(1):
|
||||
with self.assertNumQueries(2):
|
||||
tasks.recurring_nudge_schedule_hour(
|
||||
self.site_config.site.id, day, test_time_str, [schedules[0].enrollment.course.org],
|
||||
)
|
||||
|
||||
11
openedx/core/djangoapps/schedules/message_type.py
Normal file
11
openedx/core/djangoapps/schedules/message_type.py
Normal file
@@ -0,0 +1,11 @@
|
||||
import logging
|
||||
|
||||
from edx_ace.message import MessageType
|
||||
|
||||
from openedx.core.djangoapps.schedules.config import DEBUG_MESSAGE_WAFFLE_FLAG
|
||||
|
||||
|
||||
class ScheduleMessageType(MessageType):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ScheduleMessageType, self).__init__(*args, **kwargs)
|
||||
self.log_level = logging.DEBUG if DEBUG_MESSAGE_WAFFLE_FLAG.is_enabled() else None
|
||||
@@ -10,8 +10,8 @@ from courseware.models import DynamicUpgradeDeadlineConfiguration, CourseDynamic
|
||||
from edx_ace.utils import date
|
||||
from openedx.core.djangoapps.signals.signals import COURSE_START_DATE_CHANGED
|
||||
from openedx.core.djangoapps.theming.helpers import get_current_site
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleFlagNamespace, CourseWaffleFlag
|
||||
from student.models import CourseEnrollment
|
||||
from .config import CREATE_SCHEDULE_WAFFLE_FLAG
|
||||
from .models import Schedule, ScheduleConfig
|
||||
from .tasks import update_course_schedules
|
||||
|
||||
@@ -19,13 +19,6 @@ from .tasks import update_course_schedules
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
SCHEDULE_WAFFLE_FLAG = CourseWaffleFlag(
|
||||
waffle_namespace=WaffleFlagNamespace('schedules'),
|
||||
flag_name='create_schedules_for_course',
|
||||
flag_undefined_default=False
|
||||
)
|
||||
|
||||
|
||||
@receiver(post_save, sender=CourseEnrollment, dispatch_uid='create_schedule_for_enrollment')
|
||||
def create_schedule(sender, **kwargs):
|
||||
if not kwargs['created']:
|
||||
@@ -41,7 +34,7 @@ def create_schedule(sender, **kwargs):
|
||||
schedule_config = ScheduleConfig.current(current_site)
|
||||
if (
|
||||
not schedule_config.create_schedules
|
||||
and not SCHEDULE_WAFFLE_FLAG.is_enabled(enrollment.course_id)
|
||||
and not CREATE_SCHEDULE_WAFFLE_FLAG.is_enabled(enrollment.course_id)
|
||||
):
|
||||
log.debug('Schedules: Creation not enabled for this course or for this site')
|
||||
return
|
||||
|
||||
@@ -13,12 +13,13 @@ from django.db.models import Min
|
||||
from django.db.utils import DatabaseError
|
||||
from django.utils.http import urlquote
|
||||
from edx_ace import ace
|
||||
from edx_ace.message import Message, MessageType
|
||||
from edx_ace.message import Message
|
||||
from edx_ace.recipient import Recipient
|
||||
from edx_ace.utils.date import deserialize
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from edxmako.shortcuts import marketing_link
|
||||
from openedx.core.djangoapps.schedules.message_type import ScheduleMessageType
|
||||
from openedx.core.djangoapps.schedules.models import Schedule, ScheduleConfig
|
||||
|
||||
log = getLogger(__name__)
|
||||
@@ -48,7 +49,7 @@ def update_course_schedules(self, **kwargs):
|
||||
raise self.retry(kwargs=kwargs, exc=exc)
|
||||
|
||||
|
||||
class RecurringNudge(MessageType):
|
||||
class RecurringNudge(ScheduleMessageType):
|
||||
def __init__(self, day, *args, **kwargs):
|
||||
super(RecurringNudge, self).__init__(*args, **kwargs)
|
||||
self.name = "recurringnudge_day{}".format(day)
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
from collections import namedtuple
|
||||
import datetime
|
||||
import ddt
|
||||
from enum import Enum
|
||||
from mock import patch
|
||||
from pytz import utc
|
||||
|
||||
from course_modes.models import CourseMode
|
||||
from course_modes.tests.factories import CourseModeFactory
|
||||
from courseware.models import DynamicUpgradeDeadlineConfiguration
|
||||
from openedx.core.djangoapps.schedules.signals import SCHEDULE_WAFFLE_FLAG
|
||||
from openedx.core.djangoapps.schedules.signals import CREATE_SCHEDULE_WAFFLE_FLAG
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
@@ -37,40 +35,40 @@ class CreateScheduleTests(SharedModuleStoreTestCase):
|
||||
with self.assertRaises(Schedule.DoesNotExist):
|
||||
enrollment.schedule
|
||||
|
||||
@override_waffle_flag(SCHEDULE_WAFFLE_FLAG, True)
|
||||
@override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, True)
|
||||
def test_create_schedule(self, mock_get_current_site):
|
||||
site = SiteFactory.create()
|
||||
mock_get_current_site.return_value = site
|
||||
ScheduleConfigFactory.create(site=site)
|
||||
self.assert_schedule_created()
|
||||
|
||||
@override_waffle_flag(SCHEDULE_WAFFLE_FLAG, True)
|
||||
@override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, True)
|
||||
def test_no_current_site(self, mock_get_current_site):
|
||||
mock_get_current_site.return_value = None
|
||||
self.assert_schedule_not_created()
|
||||
|
||||
@override_waffle_flag(SCHEDULE_WAFFLE_FLAG, True)
|
||||
@override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, True)
|
||||
def test_schedule_config_disabled_waffle_enabled(self, mock_get_current_site):
|
||||
site = SiteFactory.create()
|
||||
mock_get_current_site.return_value = site
|
||||
ScheduleConfigFactory.create(site=site, create_schedules=False)
|
||||
self.assert_schedule_created()
|
||||
|
||||
@override_waffle_flag(SCHEDULE_WAFFLE_FLAG, False)
|
||||
@override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, False)
|
||||
def test_schedule_config_enabled_waffle_disabled(self, mock_get_current_site):
|
||||
site = SiteFactory.create()
|
||||
mock_get_current_site.return_value = site
|
||||
ScheduleConfigFactory.create(site=site, create_schedules=True)
|
||||
self.assert_schedule_created()
|
||||
|
||||
@override_waffle_flag(SCHEDULE_WAFFLE_FLAG, False)
|
||||
@override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, False)
|
||||
def test_schedule_config_disabled_waffle_disabled(self, mock_get_current_site):
|
||||
site = SiteFactory.create()
|
||||
mock_get_current_site.return_value = site
|
||||
ScheduleConfigFactory.create(site=site, create_schedules=False)
|
||||
self.assert_schedule_not_created()
|
||||
|
||||
@override_waffle_flag(SCHEDULE_WAFFLE_FLAG, True)
|
||||
@override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, True)
|
||||
def test_schedule_config_creation_enabled_instructor_paced(self, mock_get_current_site):
|
||||
site = SiteFactory.create()
|
||||
mock_get_current_site.return_value = site
|
||||
|
||||
@@ -38,7 +38,7 @@ django==1.8.18
|
||||
django-waffle==0.12.0
|
||||
djangorestframework-jwt==1.11.0
|
||||
enum34==1.1.6
|
||||
edx-ace==0.1.2
|
||||
edx-ace==0.1.4
|
||||
edx-ccx-keys==0.2.1
|
||||
edx-celeryutils==0.2.6
|
||||
edx-drf-extensions==1.2.3
|
||||
|
||||
Reference in New Issue
Block a user