Commit e2361932 by David Ormsbee

Merge pull request #15 from mcgachey/mcgachey-signals

Adding signals for scoring events.
parents 8fb070d2 835b7904
...@@ -2,3 +2,4 @@ Joe Blaylock <jrbl@stanford.edu> ...@@ -2,3 +2,4 @@ Joe Blaylock <jrbl@stanford.edu>
Will Daly <will@edx.org> Will Daly <will@edx.org>
David Ormsbee <dave@edx.org> David Ormsbee <dave@edx.org>
Stephen Sanchez <steve@edx.org> Stephen Sanchez <steve@edx.org>
Phil McGachey <phil_mcgachey@harvard.edu>
...@@ -14,7 +14,7 @@ from dogapi import dog_stats_api ...@@ -14,7 +14,7 @@ from dogapi import dog_stats_api
from submissions.serializers import ( from submissions.serializers import (
SubmissionSerializer, StudentItemSerializer, ScoreSerializer, JsonFieldError SubmissionSerializer, StudentItemSerializer, ScoreSerializer, JsonFieldError
) )
from submissions.models import Submission, StudentItem, Score, ScoreSummary from submissions.models import Submission, StudentItem, Score, ScoreSummary, score_set, score_reset
logger = logging.getLogger("submissions.api") logger = logging.getLogger("submissions.api")
...@@ -636,6 +636,14 @@ def reset_score(student_id, course_id, item_id): ...@@ -636,6 +636,14 @@ def reset_score(student_id, course_id, item_id):
# Create a "reset" score # Create a "reset" score
try: try:
Score.create_reset_score(student_item) Score.create_reset_score(student_item)
# Send a signal out to any listeners who are waiting for scoring events.
score_reset.send(
sender=None,
anonymous_user_id=student_id,
course_id=course_id,
item_id=item_id,
)
except DatabaseError: except DatabaseError:
msg = ( msg = (
u"Error occurred while reseting scores for" u"Error occurred while reseting scores for"
...@@ -716,6 +724,15 @@ def set_score(submission_uuid, points_earned, points_possible): ...@@ -716,6 +724,15 @@ def set_score(submission_uuid, points_earned, points_possible):
try: try:
score_model = score.save() score_model = score.save()
_log_score(score_model) _log_score(score_model)
# Send a signal out to any listeners who are waiting for scoring events.
score_set.send(
sender=None,
points_possible=points_possible,
points_earned=points_earned,
anonymous_user_id=submission_model.student_item.student_id,
course_id=submission_model.student_item.course_id,
item_id=submission_model.student_item.item_id,
)
except IntegrityError: except IntegrityError:
pass pass
......
...@@ -14,13 +14,24 @@ import logging ...@@ -14,13 +14,24 @@ import logging
from django.db import models, DatabaseError from django.db import models, DatabaseError
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver, Signal
from django.utils.timezone import now from django.utils.timezone import now
from django_extensions.db.fields import UUIDField from django_extensions.db.fields import UUIDField
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Signal to inform listeners that a score has been changed
score_set = Signal(providing_args=[
'points_possible', 'points_earned', 'anonymous_user_id',
'course_id', 'item_id'
]
)
# Signal to inform listeners that a score has been reset
score_reset = Signal(
providing_args=['anonymous_user_id', 'course_id', 'item_id']
)
class StudentItem(models.Model): class StudentItem(models.Model):
"""Represents a single item for a single course for a single user. """Represents a single item for a single course for a single user.
......
...@@ -3,6 +3,7 @@ import copy ...@@ -3,6 +3,7 @@ import copy
from ddt import ddt, file_data from ddt import ddt, file_data
from django.db import DatabaseError from django.db import DatabaseError
from django.dispatch import Signal
from django.core.cache import cache from django.core.cache import cache
from django.test import TestCase from django.test import TestCase
from nose.tools import raises from nose.tools import raises
...@@ -10,7 +11,7 @@ from mock import patch ...@@ -10,7 +11,7 @@ from mock import patch
import pytz import pytz
from submissions import api as api from submissions import api as api
from submissions.models import ScoreSummary, Submission, StudentItem, Score from submissions.models import ScoreSummary, Submission, StudentItem, Score, score_set
from submissions.serializers import StudentItemSerializer from submissions.serializers import StudentItemSerializer
STUDENT_ITEM = dict( STUDENT_ITEM = dict(
...@@ -226,6 +227,21 @@ class TestSubmissionsApi(TestCase): ...@@ -226,6 +227,21 @@ class TestSubmissionsApi(TestCase):
score = api.get_latest_score_for_submission(submission["uuid"]) score = api.get_latest_score_for_submission(submission["uuid"])
self._assert_score(score, 11, 12) self._assert_score(score, 11, 12)
@patch.object(score_set, 'send')
def test_set_score_signal(self, send_mock):
submission = api.create_submission(STUDENT_ITEM, ANSWER_ONE)
api.set_score(submission['uuid'], 11, 12)
# Verify that the send method was properly called
send_mock.assert_called_with(
sender=None,
points_possible=12,
points_earned=11,
anonymous_user_id=STUDENT_ITEM['student_id'],
course_id=STUDENT_ITEM['course_id'],
item_id=STUDENT_ITEM['item_id']
)
def test_get_score(self): def test_get_score(self):
submission = api.create_submission(STUDENT_ITEM, ANSWER_ONE) submission = api.create_submission(STUDENT_ITEM, ANSWER_ONE)
api.set_score(submission["uuid"], 11, 12) api.set_score(submission["uuid"], 11, 12)
...@@ -553,3 +569,4 @@ class TestSubmissionsApi(TestCase): ...@@ -553,3 +569,4 @@ class TestSubmissionsApi(TestCase):
self.assertIsNotNone(score) self.assertIsNotNone(score)
self.assertEqual(score["points_earned"], expected_points_earned) self.assertEqual(score["points_earned"], expected_points_earned)
self.assertEqual(score["points_possible"], expected_points_possible) self.assertEqual(score["points_possible"], expected_points_possible)
...@@ -8,8 +8,9 @@ from django.test import TestCase ...@@ -8,8 +8,9 @@ from django.test import TestCase
import ddt import ddt
from django.core.cache import cache from django.core.cache import cache
from django.db import DatabaseError from django.db import DatabaseError
from django.dispatch import Signal
from submissions import api as sub_api from submissions import api as sub_api
from submissions.models import Score from submissions.models import Score, score_reset
@ddt.ddt @ddt.ddt
...@@ -165,3 +166,24 @@ class TestResetScore(TestCase): ...@@ -165,3 +166,24 @@ class TestResetScore(TestCase):
self.STUDENT_ITEM['course_id'], self.STUDENT_ITEM['course_id'],
self.STUDENT_ITEM['item_id'], self.STUDENT_ITEM['item_id'],
) )
@patch.object(score_reset, 'send')
def test_reset_score_signal(self, send_mock):
# Create a submission for the student and score it
submission = sub_api.create_submission(self.STUDENT_ITEM, 'test answer')
sub_api.set_score(submission['uuid'], 1, 2)
# Reset scores
sub_api.reset_score(
self.STUDENT_ITEM['student_id'],
self.STUDENT_ITEM['course_id'],
self.STUDENT_ITEM['item_id'],
)
# Verify that the send method was properly called
send_mock.assert_called_with(
sender = None,
anonymous_user_id=self.STUDENT_ITEM['student_id'],
course_id=self.STUDENT_ITEM['course_id'],
item_id=self.STUDENT_ITEM['item_id']
)
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