Commit 4eb5311e by Sanford Student

Separating problem raw score changed and problem weighted score changed signals

For TNL-5993
parent af504fc6
......@@ -1831,14 +1831,15 @@ class TestXmoduleRuntimeEvent(TestSubmittingProblems):
self.assertIsNone(student_module.grade)
self.assertIsNone(student_module.max_grade)
@patch('lms.djangoapps.grades.signals.handlers.PROBLEM_SCORE_CHANGED.send')
@patch('lms.djangoapps.grades.signals.handlers.PROBLEM_RAW_SCORE_CHANGED.send')
def test_score_change_signal(self, send_mock):
"""Test that a Django signal is generated when a score changes"""
self.set_module_grade_using_publish(self.grade_dict)
expected_signal_kwargs = {
'sender': None,
'points_possible': self.grade_dict['max_value'],
'points_earned': self.grade_dict['value'],
'raw_possible': self.grade_dict['max_value'],
'raw_earned': self.grade_dict['value'],
'weight': None,
'user_id': self.student_user.id,
'course_id': unicode(self.course.id),
'usage_id': unicode(self.problem.location),
......
......@@ -153,7 +153,9 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase, Probl
self.student_user = User.objects.get(email=self.student)
self.factory = RequestFactory()
# Disable the score change signal to prevent other components from being pulled into tests.
self.score_changed_signal_patch = patch('lms.djangoapps.grades.signals.handlers.PROBLEM_SCORE_CHANGED.send')
self.score_changed_signal_patch = patch(
'lms.djangoapps.grades.signals.handlers.PROBLEM_WEIGHTED_SCORE_CHANGED.send'
)
self.score_changed_signal_patch.start()
def tearDown(self):
......@@ -162,7 +164,7 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase, Probl
def _stop_signal_patch(self):
"""
Stops the signal patch for the PROBLEM_SCORE_CHANGED event.
Stops the signal patch for the PROBLEM_WEIGHTED_SCORE_CHANGED event.
In case a test wants to test with the event actually
firing.
"""
......
......@@ -4,15 +4,15 @@ Signal handlers for the gating djangoapp
from django.dispatch import receiver
from gating import api as gating_api
from lms.djangoapps.grades.signals.signals import PROBLEM_SCORE_CHANGED
from lms.djangoapps.grades.signals.signals import PROBLEM_WEIGHTED_SCORE_CHANGED
from opaque_keys.edx.keys import CourseKey, UsageKey
from xmodule.modulestore.django import modulestore
@receiver(PROBLEM_SCORE_CHANGED)
@receiver(PROBLEM_WEIGHTED_SCORE_CHANGED)
def handle_score_changed(**kwargs):
"""
Receives the PROBLEM_SCORE_CHANGED signal sent by LMS when a student's score has changed
Receives the PROBLEM_WEIGHTED_SCORE_CHANGED signal sent by LMS when a student's score has changed
for a given component and triggers the evaluation of any milestone relationships
which are attached to the updated content.
......
......@@ -10,8 +10,14 @@ from openedx.core.lib.grade_utils import is_score_higher
from student.models import user_by_anonymous_id
from submissions.models import score_set, score_reset
from .signals import PROBLEM_SCORE_CHANGED, SUBSECTION_SCORE_CHANGED, SCORE_PUBLISHED
from .signals import (
PROBLEM_RAW_SCORE_CHANGED,
PROBLEM_WEIGHTED_SCORE_CHANGED,
SUBSECTION_SCORE_CHANGED,
SCORE_PUBLISHED,
)
from ..new.course_grade import CourseGradeFactory
from ..scores import weighted_score
from ..tasks import recalculate_subsection_grade
......@@ -22,9 +28,9 @@ log = getLogger(__name__)
def submissions_score_set_handler(sender, **kwargs): # pylint: disable=unused-argument
"""
Consume the score_set signal defined in the Submissions API, and convert it
to a PROBLEM_SCORE_CHANGED signal defined in this module. Converts the unicode keys
for user, course and item into the standard representation for the
PROBLEM_SCORE_CHANGED signal.
to a PROBLEM_WEIGHTED_SCORE_CHANGED signal defined in this module. Converts the
unicode keys for user, course and item into the standard representation for the
PROBLEM_WEIGHTED_SCORE_CHANGED signal.
This method expects that the kwargs dictionary will contain the following
entries (See the definition of score_set):
......@@ -42,10 +48,10 @@ def submissions_score_set_handler(sender, **kwargs): # pylint: disable=unused-a
if user is None:
return
PROBLEM_SCORE_CHANGED.send(
PROBLEM_WEIGHTED_SCORE_CHANGED.send(
sender=None,
points_earned=points_earned,
points_possible=points_possible,
weighted_earned=points_earned,
weighted_possible=points_possible,
user_id=user.id,
course_id=course_id,
usage_id=usage_id
......@@ -56,9 +62,9 @@ def submissions_score_set_handler(sender, **kwargs): # pylint: disable=unused-a
def submissions_score_reset_handler(sender, **kwargs): # pylint: disable=unused-argument
"""
Consume the score_reset signal defined in the Submissions API, and convert
it to a PROBLEM_SCORE_CHANGED signal indicating that the score has been set to 0/0.
Converts the unicode keys for user, course and item into the standard
representation for the PROBLEM_SCORE_CHANGED signal.
it to a PROBLEM_WEIGHTED_SCORE_CHANGED signal indicating that the score
has been set to 0/0. Converts the unicode keys for user, course and item
into the standard representation for the PROBLEM_WEIGHTED_SCORE_CHANGED signal.
This method expects that the kwargs dictionary will contain the following
entries (See the definition of score_reset):
......@@ -72,10 +78,10 @@ def submissions_score_reset_handler(sender, **kwargs): # pylint: disable=unused
if user is None:
return
PROBLEM_SCORE_CHANGED.send(
PROBLEM_WEIGHTED_SCORE_CHANGED.send(
sender=None,
points_earned=0,
points_possible=0,
weighted_earned=0,
weighted_possible=0,
user_id=user.id,
course_id=course_id,
usage_id=usage_id
......@@ -106,10 +112,11 @@ def score_published_handler(sender, block, user, raw_earned, raw_possible, only_
if update_score:
set_score(user.id, block.location, raw_earned, raw_possible)
PROBLEM_SCORE_CHANGED.send(
PROBLEM_RAW_SCORE_CHANGED.send(
sender=None,
points_earned=raw_earned,
points_possible=raw_possible,
raw_earned=raw_earned,
raw_possible=raw_possible,
weight=getattr(block, 'weight', None),
user_id=user.id,
course_id=unicode(block.location.course_key),
usage_id=unicode(block.location),
......@@ -118,10 +125,38 @@ def score_published_handler(sender, block, user, raw_earned, raw_possible, only_
return update_score
@receiver(PROBLEM_SCORE_CHANGED)
@receiver(PROBLEM_RAW_SCORE_CHANGED)
def problem_raw_score_changed_handler(sender, **kwargs): # pylint: disable=unused-argument
"""
Handles the raw score changed signal, converting the score to a
weighted score and firing the PROBLEM_WEIGHTED_SCORE_CHANGED signal.
"""
if kwargs['raw_possible'] is not None:
weighted_earned, weighted_possible = weighted_score(
kwargs['raw_earned'],
kwargs['raw_possible'],
kwargs['weight'],
)
else: # TODO: remove as part of TNL-5982
weighted_earned, weighted_possible = kwargs['raw_earned'], kwargs['raw_possible']
PROBLEM_WEIGHTED_SCORE_CHANGED.send(
sender=None,
weighted_earned=weighted_earned,
weighted_possible=weighted_possible,
user_id=kwargs['user_id'],
course_id=kwargs['course_id'],
usage_id=kwargs['usage_id'],
only_if_higher=kwargs['only_if_higher'],
score_deleted=kwargs.get('score_deleted', False),
)
@receiver(PROBLEM_WEIGHTED_SCORE_CHANGED)
def enqueue_subsection_update(sender, **kwargs): # pylint: disable=unused-argument
"""
Handles the PROBLEM_SCORE_CHANGED signal by enqueueing a subsection update operation to occur asynchronously.
Handles the PROBLEM_WEIGHTED_SCORE_CHANGED signal by
enqueueing a subsection update operation to occur asynchronously.
"""
result = recalculate_subsection_grade.apply_async(
kwargs=dict(
......@@ -129,8 +164,8 @@ def enqueue_subsection_update(sender, **kwargs): # pylint: disable=unused-argum
course_id=kwargs['course_id'],
usage_id=kwargs['usage_id'],
only_if_higher=kwargs.get('only_if_higher'),
raw_earned=kwargs.get('points_earned'),
raw_possible=kwargs.get('points_possible'),
weighted_earned=kwargs.get('weighted_earned'),
weighted_possible=kwargs.get('weighted_possible'),
score_deleted=kwargs.get('score_deleted', False),
)
)
......
......@@ -4,19 +4,39 @@ Grades related signals.
from django.dispatch import Signal
# Signal that indicates that a user's score for a problem has been updated.
# This signal is generated when a scoring event occurs either within the core
# platform or in the Submissions module. Note that this signal will be triggered
# Signal that indicates that a user's raw score for a problem has been updated.
# This signal is generated when a scoring event occurs within the core
# platform. Note that this signal will be triggered
# regardless of the new and previous values of the score (i.e. it may be the
# case that this signal is generated when a user re-attempts a problem but
# receives the same score).
PROBLEM_SCORE_CHANGED = Signal(
PROBLEM_RAW_SCORE_CHANGED = Signal(
providing_args=[
'user_id', # Integer User ID
'course_id', # Unicode string representing the course
'usage_id', # Unicode string indicating the courseware instance
'points_earned', # Score obtained by the user
'points_possible', # Maximum score available for the exercise
'raw_earned', # Score obtained by the user
'raw_possible', # Maximum score available for the exercise
'weight', # Weight of the problem
'only_if_higher', # Boolean indicating whether updates should be
# made only if the new score is higher than previous.
]
)
# Signal that indicates that a user's weighted score for a problem has been updated.
# This signal is generated when a scoring event occurs in the Submissions module
# or a PROBLEM_RAW_SCORE_CHANGED event is handled in the core platform.
# Note that this signal will be triggered
# regardless of the new and previous values of the score (i.e. it may be the
# case that this signal is generated when a user re-attempts a problem but
# receives the same score).
PROBLEM_WEIGHTED_SCORE_CHANGED = Signal(
providing_args=[
'user_id', # Integer User ID
'course_id', # Unicode string representing the course
'usage_id', # Unicode string indicating the courseware instance
'weighted_earned', # Score obtained by the user
'weighted_possible', # Maximum score available for the exercise
'only_if_higher', # Boolean indicating whether updates should be
# made only if the new score is higher than previous.
]
......@@ -25,8 +45,8 @@ PROBLEM_SCORE_CHANGED = Signal(
# Signal that indicates that a user's score for a problem has been published
# for possible persistence and update. Typically, most clients should listen
# to the PROBLEM_SCORE_CHANGED signal instead, since that is signalled only after the
# problem's score is changed.
# to the PROBLEM_WEIGHTED_SCORE_CHANGED signal instead, since that is signalled
# only after the problem's score is changed.
SCORE_PUBLISHED = Signal(
providing_args=[
'block', # Course block object
......@@ -40,8 +60,8 @@ SCORE_PUBLISHED = Signal(
# Signal that indicates that a user's score for a subsection has been updated.
# This is a downstream signal of PROBLEM_SCORE_CHANGED sent for each affected containing
# subsection.
# This is a downstream signal of PROBLEM_WEIGHTED_SCORE_CHANGED sent for each
# affected containing subsection.
SUBSECTION_SCORE_CHANGED = Signal(
providing_args=[
'course', # Course object
......
......@@ -23,7 +23,9 @@ log = getLogger(__name__)
@task(default_retry_delay=30, routing_key=settings.RECALCULATE_GRADES_ROUTING_KEY)
def recalculate_subsection_grade(user_id, course_id, usage_id, only_if_higher, raw_earned, raw_possible, **kwargs):
def recalculate_subsection_grade(
user_id, course_id, usage_id, only_if_higher, weighted_earned, weighted_possible, **kwargs
):
"""
Updates a saved subsection grade.
......@@ -34,9 +36,9 @@ def recalculate_subsection_grade(user_id, course_id, usage_id, only_if_higher, r
only_if_higher (boolean): indicating whether grades should
be updated only if the new raw_earned is higher than the
previous value.
raw_earned (float): the raw points the learner earned on the
weighted_earned (float): the weighted points the learner earned on the
problem that triggered the update.
raw_possible (float): the max raw points the leaner could have
weighted_possible (float): the max weighted points the leaner could have
earned on the problem.
score_deleted (boolean): indicating whether the grade change is
a result of the problem's score being deleted.
......@@ -53,10 +55,10 @@ def recalculate_subsection_grade(user_id, course_id, usage_id, only_if_higher, r
# creator's process hasn't committed before the task initiates in the worker
# process.
if not _has_database_updated_with_new_score(
user_id, scored_block_usage_key, raw_earned, raw_possible, score_deleted,
user_id, scored_block_usage_key, weighted_earned, weighted_possible, score_deleted,
):
raise _retry_recalculate_subsection_grade(
user_id, course_id, usage_id, only_if_higher, raw_earned, raw_possible, score_deleted,
user_id, course_id, usage_id, only_if_higher, weighted_earned, weighted_possible, score_deleted,
)
_update_subsection_grades(
......@@ -66,8 +68,8 @@ def recalculate_subsection_grade(user_id, course_id, usage_id, only_if_higher, r
course_id,
user_id,
usage_id,
raw_earned,
raw_possible,
weighted_earned,
weighted_possible,
score_deleted,
)
......@@ -100,8 +102,8 @@ def _update_subsection_grades(
course_id,
user_id,
usage_id,
raw_earned,
raw_possible,
weighted_earned,
weighted_possible,
score_deleted,
):
"""
......@@ -138,12 +140,12 @@ def _update_subsection_grades(
except DatabaseError as exc:
raise _retry_recalculate_subsection_grade(
user_id, course_id, usage_id, only_if_higher, raw_earned, raw_possible, score_deleted, exc,
user_id, course_id, usage_id, only_if_higher, weighted_earned, weighted_possible, score_deleted, exc,
)
def _retry_recalculate_subsection_grade(
user_id, course_id, usage_id, only_if_higher, raw_earned, raw_possible, score_deleted, exc=None,
user_id, course_id, usage_id, only_if_higher, weighted_earned, weighted_possible, score_deleted, exc=None,
):
"""
Calls retry for the recalculate_subsection_grade task with the
......@@ -155,8 +157,8 @@ def _retry_recalculate_subsection_grade(
course_id=course_id,
usage_id=usage_id,
only_if_higher=only_if_higher,
raw_earned=raw_earned,
raw_possible=raw_possible,
weighted_earned=weighted_earned,
weighted_possible=weighted_possible,
score_deleted=score_deleted,
),
exc=exc,
......
......@@ -12,6 +12,7 @@ from ..signals.handlers import (
enqueue_subsection_update,
submissions_score_set_handler,
submissions_score_reset_handler,
problem_raw_score_changed_handler,
)
UUID_REGEX = re.compile(ur'%(hex)s{8}-%(hex)s{4}-%(hex)s{4}-%(hex)s{4}-%(hex)s{12}' % {'hex': u'[0-9a-f]'})
......@@ -31,22 +32,39 @@ SUBMISSION_RESET_KWARGS = {
'item_id': 'i4x://org/course/usage/123456'
}
PROBLEM_RAW_SCORE_CHANGED_KWARGS = {
'raw_earned': 1.0,
'raw_possible': 2.0,
'weight': 4,
'user_id': 'UserID',
'course_id': 'CourseID',
'usage_id': 'i4x://org/course/usage/123456',
'only_if_higher': False,
'score_deleted': True,
}
@ddt.ddt
class SubmissionSignalRelayTest(TestCase):
class ScoreChangedSignalRelayTest(TestCase):
"""
Tests to ensure that the courseware module correctly catches score_set and
score_reset signals from the Submissions API and recasts them as LMS
signals. This ensures that listeners in the LMS only have to handle one type
of signal for all scoring events.
Tests to ensure that the courseware module correctly catches
(a) score_set and score_reset signals from the Submissions API
(b) LMS PROBLEM_RAW_SCORE_CHANGED signals
and recasts them as LMS PROBLEM_WEIGHTED_SCORE_CHANGED signals.
This ensures that listeners in the LMS only have to handle one type
of signal for all scoring events regardless of their origin.
"""
def setUp(self):
"""
Configure mocks for all the dependencies of the render method
"""
super(SubmissionSignalRelayTest, self).setUp()
self.signal_mock = self.setup_patch('lms.djangoapps.grades.signals.signals.PROBLEM_SCORE_CHANGED.send', None)
super(ScoreChangedSignalRelayTest, self).setUp()
self.signal_mock = self.setup_patch(
'lms.djangoapps.grades.signals.signals.PROBLEM_WEIGHTED_SCORE_CHANGED.send',
None,
)
self.user_mock = MagicMock()
self.user_mock.id = 42
self.get_user_mock = self.setup_patch(
......@@ -72,15 +90,16 @@ class SubmissionSignalRelayTest(TestCase):
def test_score_set_signal_handler(self, handler, kwargs, earned, possible):
"""
Ensure that on receipt of a score_(re)set signal from the Submissions API,
the signal handler correctly converts it to a PROBLEM_SCORE_CHANGED signal.
the signal handler correctly converts it to a PROBLEM_WEIGHTED_SCORE_CHANGED
signal.
Also ensures that the handler calls user_by_anonymous_id correctly.
"""
handler(None, **kwargs)
expected_set_kwargs = {
'sender': None,
'points_possible': possible,
'points_earned': earned,
'weighted_possible': possible,
'weighted_earned': earned,
'user_id': self.user_mock.id,
'course_id': 'CourseID',
'usage_id': 'i4x://org/course/usage/123456'
......@@ -122,6 +141,36 @@ class SubmissionSignalRelayTest(TestCase):
handler(None, **kwargs)
self.signal_mock.assert_not_called()
def test_raw_score_changed_signal_handler(self):
problem_raw_score_changed_handler(None, **PROBLEM_RAW_SCORE_CHANGED_KWARGS)
expected_set_kwargs = {
'sender': None,
'weighted_earned': 2.0,
'weighted_possible': 4.0,
'user_id': 'UserID',
'course_id': 'CourseID',
'usage_id': 'i4x://org/course/usage/123456',
'only_if_higher': False,
'score_deleted': True,
}
self.signal_mock.assert_called_with(**expected_set_kwargs)
def test_raw_score_changed_score_deleted_optional(self):
local_kwargs = PROBLEM_RAW_SCORE_CHANGED_KWARGS.copy()
del local_kwargs['score_deleted']
problem_raw_score_changed_handler(None, **local_kwargs)
expected_set_kwargs = {
'sender': None,
'weighted_earned': 2.0,
'weighted_possible': 4.0,
'user_id': 'UserID',
'course_id': 'CourseID',
'usage_id': 'i4x://org/course/usage/123456',
'only_if_higher': False,
'score_deleted': False,
}
self.signal_mock.assert_called_with(**expected_set_kwargs)
@patch('lms.djangoapps.grades.signals.handlers.log.info')
def test_problem_score_changed_logging(self, mocklog):
enqueue_subsection_update(
......
......@@ -18,7 +18,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls
from lms.djangoapps.grades.config.models import PersistentGradesEnabledFlag
from lms.djangoapps.grades.signals.signals import PROBLEM_SCORE_CHANGED
from lms.djangoapps.grades.signals.signals import PROBLEM_WEIGHTED_SCORE_CHANGED
from lms.djangoapps.grades.tasks import recalculate_subsection_grade
......@@ -50,9 +50,9 @@ class RecalculateSubsectionGradeTest(ModuleStoreTestCase):
self.sequential = ItemFactory.create(parent=self.chapter, category='sequential', display_name="Sequential1")
self.problem = ItemFactory.create(parent=self.sequential, category='problem', display_name='Problem')
self.problem_score_changed_kwargs = OrderedDict([
('points_earned', 1.0),
('points_possible', 2.0),
self.problem_weighted_score_changed_kwargs = OrderedDict([
('weighted_earned', 1.0),
('weighted_possible', 2.0),
('user_id', self.user.id),
('course_id', unicode(self.course.id)),
('usage_id', unicode(self.problem.location)),
......@@ -64,8 +64,8 @@ class RecalculateSubsectionGradeTest(ModuleStoreTestCase):
('course_id', unicode(self.course.id)),
('usage_id', unicode(self.problem.location)),
('only_if_higher', None),
('raw_earned', 1.0),
('raw_possible', 2.0),
('weighted_earned', 1.0),
('weighted_possible', 2.0),
('score_deleted', False),
])
......@@ -82,17 +82,17 @@ class RecalculateSubsectionGradeTest(ModuleStoreTestCase):
with patch("lms.djangoapps.grades.tasks.get_score", return_value=score):
yield
def test_problem_score_changed_queues_task(self):
def test_problem_weighted_score_changed_queues_task(self):
"""
Ensures that the PROBLEM_SCORE_CHANGED signal enqueues the correct task.
Ensures that the PROBLEM_WEIGHTED_SCORE_CHANGED signal enqueues the correct task.
"""
self.set_up_course()
send_args = self.problem_score_changed_kwargs
send_args = self.problem_weighted_score_changed_kwargs
with self.mock_get_score() and patch(
'lms.djangoapps.grades.tasks.recalculate_subsection_grade.apply_async',
return_value=None
) as mock_task_apply:
PROBLEM_SCORE_CHANGED.send(sender=None, **send_args)
PROBLEM_WEIGHTED_SCORE_CHANGED.send(sender=None, **send_args)
mock_task_apply.assert_called_once_with(kwargs=self.recalculate_subsection_grade_kwargs)
@patch('lms.djangoapps.grades.signals.signals.SUBSECTION_SCORE_CHANGED.send')
......
......@@ -15,8 +15,7 @@ from django.utils.translation import override as override_language
from course_modes.models import CourseMode
from courseware.models import StudentModule
from edxmako.shortcuts import render_to_string
from lms.djangoapps.grades.scores import weighted_score
from lms.djangoapps.grades.signals.signals import PROBLEM_SCORE_CHANGED
from lms.djangoapps.grades.signals.signals import PROBLEM_RAW_SCORE_CHANGED
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.user_api.models import UserPreference
......@@ -290,28 +289,22 @@ def _reset_module_attempts(studentmodule):
def _fire_score_changed_for_block(course_id, student, block, module_state_key):
"""
Fires a PROBLEM_SCORE_CHANGED event for the given module. The earned points are
always zero. We must retrieve the possible points from the XModule, as
noted below.
Fires a PROBLEM_RAW_SCORE_CHANGED event for the given module.
The earned points are always zero. We must retrieve the possible points
from the XModule, as noted below.
"""
if block and block.has_score:
max_score = block.max_score()
if max_score is None:
return
else:
points_earned, points_possible = weighted_score(0, max_score, getattr(block, 'weight', None))
else:
points_earned, points_possible = 0, 0
PROBLEM_SCORE_CHANGED.send(
sender=None,
points_possible=points_possible,
points_earned=points_earned,
user_id=student.id,
course_id=unicode(course_id),
usage_id=unicode(module_state_key),
score_deleted=True,
)
if block and block.has_score and block.max_score() is not None:
PROBLEM_RAW_SCORE_CHANGED.send(
sender=None,
raw_possible=0,
raw_earned=block.max_score(),
weight=getattr(block, 'weight', None),
user_id=student.id,
course_id=unicode(course_id),
usage_id=unicode(module_state_key),
score_deleted=True,
only_if_higher=False,
)
def get_email_params(course, auto_enroll, secure=True, course_key=None, display_name=None):
......
......@@ -3190,7 +3190,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
})
self.assertEqual(response.status_code, 400)
@patch('lms.djangoapps.grades.signals.handlers.PROBLEM_SCORE_CHANGED.send')
@patch('lms.djangoapps.grades.signals.handlers.PROBLEM_WEIGHTED_SCORE_CHANGED.send')
def test_reset_student_attempts_delete(self, _mock_signal):
""" Test delete single student state. """
url = reverse('reset_student_attempts', kwargs={'course_id': self.course.id.to_deprecated_string()})
......
......@@ -374,7 +374,7 @@ class TestInstructorEnrollmentStudentModule(SharedModuleStoreTestCase):
reset_student_attempts(self.course_key, self.user, msk, requesting_user=self.user)
self.assertEqual(json.loads(module().state)['attempts'], 0)
@mock.patch('lms.djangoapps.grades.signals.handlers.PROBLEM_SCORE_CHANGED.send')
@mock.patch('lms.djangoapps.grades.signals.handlers.PROBLEM_WEIGHTED_SCORE_CHANGED.send')
def test_delete_student_attempts(self, _mock_signal):
msk = self.course_key.make_usage_key('dummy', 'module')
original_state = json.dumps({'attempts': 32, 'otherstuff': 'alsorobots'})
......@@ -400,7 +400,7 @@ class TestInstructorEnrollmentStudentModule(SharedModuleStoreTestCase):
# Disable the score change signal to prevent other components from being
# pulled into tests.
@mock.patch('lms.djangoapps.grades.signals.handlers.PROBLEM_SCORE_CHANGED.send')
@mock.patch('lms.djangoapps.grades.signals.handlers.PROBLEM_WEIGHTED_SCORE_CHANGED.send')
def test_delete_submission_scores(self, _mock_signal):
user = UserFactory()
problem_location = self.course_key.make_usage_key('dummy', 'module')
......
......@@ -49,7 +49,7 @@ class InstructorServiceTests(SharedModuleStoreTestCase):
state=json.dumps({'attempts': 2}),
)
@mock.patch('lms.djangoapps.grades.signals.handlers.PROBLEM_SCORE_CHANGED.send')
@mock.patch('lms.djangoapps.grades.signals.handlers.PROBLEM_WEIGHTED_SCORE_CHANGED.send')
def test_reset_student_attempts_delete(self, _mock_signal):
"""
Test delete student state.
......
......@@ -8,7 +8,7 @@ from django.dispatch import receiver
import logging
from lms.djangoapps.grades import progress
from lms.djangoapps.grades.signals.signals import PROBLEM_SCORE_CHANGED
from lms.djangoapps.grades.signals.signals import PROBLEM_WEIGHTED_SCORE_CHANGED
from lms import CELERY_APP
from lti_provider.models import GradedAssignment
import lti_provider.outcomes as outcomes
......@@ -19,14 +19,14 @@ from xmodule.modulestore.django import modulestore
log = logging.getLogger("edx.lti_provider")
@receiver(PROBLEM_SCORE_CHANGED)
@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_SCORE_CHANGED for a description of the signal.
PROBLEM_WEIGHTED_SCORE_CHANGED for a description of the signal.
"""
points_possible = kwargs.get('points_possible', None)
points_earned = kwargs.get('points_earned', None)
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)
......
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