Merge pull request #16428 from edx/jeskew/email_mkting_lti_prov_to_appconfig_ready
Move lti_provider/email_marketing startup to AppConfig ready.
This commit is contained in:
@@ -1,10 +1,15 @@
|
||||
|
||||
"""
|
||||
Configuration for the edxmako Django application.
|
||||
"""
|
||||
from django.apps import AppConfig
|
||||
from django.conf import settings
|
||||
from . import add_lookup, clear_lookups
|
||||
|
||||
|
||||
class EdxMakoConfig(AppConfig):
|
||||
"""
|
||||
Configuration class for the edxmako Django application.
|
||||
"""
|
||||
name = 'edxmako'
|
||||
verbose_name = "edX Mako Templating"
|
||||
|
||||
|
||||
16
lms/djangoapps/email_marketing/apps.py
Normal file
16
lms/djangoapps/email_marketing/apps.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
Configuration for the email_marketing Django application.
|
||||
"""
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class EmailMarketingConfig(AppConfig):
|
||||
"""
|
||||
Configuration class for the email_marketing Django application.
|
||||
"""
|
||||
name = 'email_marketing'
|
||||
verbose_name = "Email Marketing"
|
||||
|
||||
def ready(self):
|
||||
# Register the signal handlers.
|
||||
from . import signals # pylint: disable=unused-import
|
||||
@@ -1,3 +0,0 @@
|
||||
""" email_marketing app. """
|
||||
# this is here to support registering the signals in signals.py
|
||||
from email_marketing import signals # pylint: disable=unused-import
|
||||
16
lms/djangoapps/lti_provider/apps.py
Normal file
16
lms/djangoapps/lti_provider/apps.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
Configuration for the lti_provider Django application.
|
||||
"""
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class LtiProviderConfig(AppConfig):
|
||||
"""
|
||||
Configuration class for the lti_provider Django application.
|
||||
"""
|
||||
name = 'lti_provider'
|
||||
verbose_name = "LTI Provider"
|
||||
|
||||
def ready(self):
|
||||
# Import the tasks module to ensure that signal handlers are registered.
|
||||
from . import signals # pylint: disable=unused-import
|
||||
69
lms/djangoapps/lti_provider/signals.py
Normal file
69
lms/djangoapps/lti_provider/signals.py
Normal file
@@ -0,0 +1,69 @@
|
||||
"""
|
||||
Signals handlers for the lti_provider Django app.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from django.dispatch import receiver
|
||||
|
||||
import lti_provider.outcomes as outcomes
|
||||
from lms.djangoapps.grades.signals.signals import PROBLEM_WEIGHTED_SCORE_CHANGED
|
||||
from lti_provider.views import parse_course_and_usage_keys
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from .tasks import send_composite_outcome, send_leaf_outcome
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def increment_assignment_versions(course_key, usage_key, user_id):
|
||||
"""
|
||||
Update the version numbers for all assignments that are affected by a score
|
||||
change event. Returns a list of all affected assignments.
|
||||
"""
|
||||
problem_descriptor = modulestore().get_item(usage_key)
|
||||
# Get all assignments involving the current problem for which the campus LMS
|
||||
# is expecting a grade. There may be many possible graded assignments, if
|
||||
# a problem has been added several times to a course at different
|
||||
# granularities (such as the unit or the vertical).
|
||||
assignments = outcomes.get_assignments_for_problem(
|
||||
problem_descriptor, user_id, course_key
|
||||
)
|
||||
for assignment in assignments:
|
||||
assignment.version_number += 1
|
||||
assignment.save()
|
||||
return assignments
|
||||
|
||||
|
||||
@receiver(PROBLEM_WEIGHTED_SCORE_CHANGED)
|
||||
def score_changed_handler(sender, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
Consume signals that indicate score changes. See the definition of
|
||||
PROBLEM_WEIGHTED_SCORE_CHANGED for a description of the signal.
|
||||
"""
|
||||
points_possible = kwargs.get('weighted_possible', None)
|
||||
points_earned = kwargs.get('weighted_earned', None)
|
||||
user_id = kwargs.get('user_id', None)
|
||||
course_id = kwargs.get('course_id', None)
|
||||
usage_id = kwargs.get('usage_id', None)
|
||||
|
||||
if None not in (points_earned, points_possible, user_id, course_id):
|
||||
course_key, usage_key = parse_course_and_usage_keys(course_id, usage_id)
|
||||
assignments = increment_assignment_versions(course_key, usage_key, user_id)
|
||||
for assignment in assignments:
|
||||
if assignment.usage_key == usage_key:
|
||||
send_leaf_outcome.delay(
|
||||
assignment.id, points_earned, points_possible
|
||||
)
|
||||
else:
|
||||
send_composite_outcome.apply_async(
|
||||
(user_id, course_id, assignment.id, assignment.version_number),
|
||||
countdown=settings.LTI_AGGREGATE_SCORE_PASSBACK_DELAY
|
||||
)
|
||||
else:
|
||||
log.error(
|
||||
"Outcome Service: Required signal parameter is None. "
|
||||
"points_possible: %s, points_earned: %s, user_id: %s, "
|
||||
"course_id: %s, usage_id: %s",
|
||||
points_possible, points_earned, user_id, course_id, usage_id
|
||||
)
|
||||
@@ -1,4 +0,0 @@
|
||||
"""Code run at server start up to initialize the lti_provider app."""
|
||||
|
||||
# Import the tasks module to ensure that signal handlers are registered.
|
||||
import lms.djangoapps.lti_provider.tasks # pylint: disable=unused-import
|
||||
@@ -4,73 +4,16 @@ Asynchronous tasks for the LTI provider app.
|
||||
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.dispatch import receiver
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
import lti_provider.outcomes as outcomes
|
||||
from lms import CELERY_APP
|
||||
from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
|
||||
from lms.djangoapps.grades.signals.signals import PROBLEM_WEIGHTED_SCORE_CHANGED
|
||||
from lti_provider.models import GradedAssignment
|
||||
from lti_provider.views import parse_course_and_usage_keys
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
log = logging.getLogger("edx.lti_provider")
|
||||
|
||||
|
||||
@receiver(PROBLEM_WEIGHTED_SCORE_CHANGED)
|
||||
def score_changed_handler(sender, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
Consume signals that indicate score changes. See the definition of
|
||||
PROBLEM_WEIGHTED_SCORE_CHANGED for a description of the signal.
|
||||
"""
|
||||
points_possible = kwargs.get('weighted_possible', None)
|
||||
points_earned = kwargs.get('weighted_earned', None)
|
||||
user_id = kwargs.get('user_id', None)
|
||||
course_id = kwargs.get('course_id', None)
|
||||
usage_id = kwargs.get('usage_id', None)
|
||||
|
||||
if None not in (points_earned, points_possible, user_id, course_id):
|
||||
course_key, usage_key = parse_course_and_usage_keys(course_id, usage_id)
|
||||
assignments = increment_assignment_versions(course_key, usage_key, user_id)
|
||||
for assignment in assignments:
|
||||
if assignment.usage_key == usage_key:
|
||||
send_leaf_outcome.delay(
|
||||
assignment.id, points_earned, points_possible
|
||||
)
|
||||
else:
|
||||
send_composite_outcome.apply_async(
|
||||
(user_id, course_id, assignment.id, assignment.version_number),
|
||||
countdown=settings.LTI_AGGREGATE_SCORE_PASSBACK_DELAY
|
||||
)
|
||||
else:
|
||||
log.error(
|
||||
"Outcome Service: Required signal parameter is None. "
|
||||
"points_possible: %s, points_earned: %s, user_id: %s, "
|
||||
"course_id: %s, usage_id: %s",
|
||||
points_possible, points_earned, user_id, course_id, usage_id
|
||||
)
|
||||
|
||||
|
||||
def increment_assignment_versions(course_key, usage_key, user_id):
|
||||
"""
|
||||
Update the version numbers for all assignments that are affected by a score
|
||||
change event. Returns a list of all affected assignments.
|
||||
"""
|
||||
problem_descriptor = modulestore().get_item(usage_key)
|
||||
# Get all assignments involving the current problem for which the campus LMS
|
||||
# is expecting a grade. There may be many possible graded assignments, if
|
||||
# a problem has been added several times to a course at different
|
||||
# granularities (such as the unit or the vertical).
|
||||
assignments = outcomes.get_assignments_for_problem(
|
||||
problem_descriptor, user_id, course_key
|
||||
)
|
||||
for assignment in assignments:
|
||||
assignment.version_number += 1
|
||||
assignment.save()
|
||||
return assignments
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@CELERY_APP.task(name='lti_provider.tasks.send_composite_outcome')
|
||||
|
||||
@@ -869,7 +869,7 @@ CREDIT_PROVIDER_SECRET_KEYS = AUTH_TOKENS.get("CREDIT_PROVIDER_SECRET_KEYS", {})
|
||||
|
||||
##################### LTI Provider #####################
|
||||
if FEATURES.get('ENABLE_LTI_PROVIDER'):
|
||||
INSTALLED_APPS.append('lti_provider')
|
||||
INSTALLED_APPS.append('lti_provider.apps.LtiProviderConfig')
|
||||
AUTHENTICATION_BACKENDS.append('lti_provider.users.LtiBackend')
|
||||
|
||||
LTI_USER_EMAIL_DOMAIN = ENV_TOKENS.get('LTI_USER_EMAIL_DOMAIN', 'lti.example.com')
|
||||
|
||||
@@ -2289,7 +2289,7 @@ INSTALLED_APPS = [
|
||||
'django_sites_extensions',
|
||||
|
||||
# Email marketing integration
|
||||
'email_marketing',
|
||||
'email_marketing.apps.EmailMarketingConfig',
|
||||
|
||||
# additional release utilities to ease automation
|
||||
'release_util',
|
||||
|
||||
@@ -571,7 +571,7 @@ PROFILE_IMAGE_MIN_BYTES = 100
|
||||
|
||||
# Enable the LTI provider feature for testing
|
||||
FEATURES['ENABLE_LTI_PROVIDER'] = True
|
||||
INSTALLED_APPS.append('lti_provider')
|
||||
INSTALLED_APPS.append('lti_provider.apps.LtiProviderConfig')
|
||||
AUTHENTICATION_BACKENDS.append('lti_provider.users.LtiBackend')
|
||||
|
||||
# ORGANIZATIONS
|
||||
|
||||
@@ -319,7 +319,7 @@ if FEATURES.get('INDIVIDUAL_DUE_DATES'):
|
||||
|
||||
##################### LTI Provider #####################
|
||||
if FEATURES.get('ENABLE_LTI_PROVIDER'):
|
||||
INSTALLED_APPS.append('lti_provider')
|
||||
INSTALLED_APPS.append('lti_provider.apps.LtiProviderConfig')
|
||||
AUTHENTICATION_BACKENDS.append('lti_provider.users.LtiBackend')
|
||||
|
||||
################################ Settings for Credentials Service ################################
|
||||
|
||||
@@ -231,14 +231,7 @@ class TestUserPreferenceMiddleware(TestCase):
|
||||
# No preference yet, should write to the database
|
||||
|
||||
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), None)
|
||||
|
||||
# The 'email_marketing' app is installed in the LMS env but not the CMS env. It listens for the
|
||||
# USER_FIELD_CHANGED signal (utils.model_utils) and does a query to check the EmailMarketingConfiguration
|
||||
# table to see if Sailthru integreation is enabled.
|
||||
expected_queries = 6 if 'email_marketing' in settings.INSTALLED_APPS else 5
|
||||
with self.assertNumQueries(expected_queries):
|
||||
self.middleware.process_request(self.request)
|
||||
|
||||
self.middleware.process_request(self.request)
|
||||
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'es')
|
||||
|
||||
response = mock.Mock(spec=HttpResponse)
|
||||
@@ -261,14 +254,7 @@ class TestUserPreferenceMiddleware(TestCase):
|
||||
# Cookie changed, should write to the database again
|
||||
|
||||
self.request.COOKIES[settings.LANGUAGE_COOKIE] = 'en'
|
||||
|
||||
# The 'email_marketing' app is installed in the LMS env but not the CMS env. It listens for the
|
||||
# USER_FIELD_CHANGED signal (utils.model_utils) and does a query to check the EmailMarketingConfiguration
|
||||
# table to see if Sailthru integreation is enabled.
|
||||
expected_queries = 6 if 'email_marketing' in settings.INSTALLED_APPS else 5
|
||||
with self.assertNumQueries(expected_queries):
|
||||
self.middleware.process_request(self.request)
|
||||
|
||||
self.middleware.process_request(self.request)
|
||||
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'en')
|
||||
|
||||
with self.assertNumQueries(1):
|
||||
|
||||
Reference in New Issue
Block a user