Merge pull request #15127 from edx/yro_refactorCMSsignalhandling
Refactor CMS Signal Handling
This commit is contained in:
22
cms/djangoapps/contentstore/apps.py
Normal file
22
cms/djangoapps/contentstore/apps.py
Normal file
@@ -0,0 +1,22 @@
|
||||
"""
|
||||
Contentstore Application Configuration
|
||||
|
||||
Above-modulestore level signal handlers are connected here.
|
||||
"""
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ContentstoreConfig(AppConfig):
|
||||
"""
|
||||
Application Configuration for Grades.
|
||||
"""
|
||||
name = u'contentstore'
|
||||
|
||||
def ready(self):
|
||||
"""
|
||||
Connect handlers to signals.
|
||||
"""
|
||||
# Can't import models at module level in AppConfigs, and models get
|
||||
# included from the signal handlers
|
||||
from .signals import handlers # pylint: disable=unused-variable
|
||||
0
cms/djangoapps/contentstore/signals/__init__.py
Normal file
0
cms/djangoapps/contentstore/signals/__init__.py
Normal file
@@ -4,7 +4,7 @@ import logging
|
||||
from datetime import datetime
|
||||
from pytz import UTC
|
||||
|
||||
from django.dispatch import receiver, Signal
|
||||
from django.dispatch import receiver
|
||||
|
||||
from xmodule.modulestore.django import modulestore, SignalHandler
|
||||
from contentstore.courseware_index import CoursewareSearchIndexer, LibrarySearchIndexer
|
||||
@@ -17,17 +17,6 @@ from util.module_utils import yield_dynamic_descriptor_descendants
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Signal that indicates that a course grading policy has been updated.
|
||||
# This signal is generated when a grading policy change occurs within
|
||||
# modulestore for either course or subsection changes.
|
||||
GRADING_POLICY_CHANGED = Signal(
|
||||
providing_args=[
|
||||
'user_id', # Integer User ID
|
||||
'course_id', # Unicode string representing the course
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@receiver(SignalHandler.course_published)
|
||||
def listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
@@ -50,10 +39,9 @@ def listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable=
|
||||
|
||||
# Finally call into the course search subsystem
|
||||
# to kick off an indexing action
|
||||
|
||||
if CoursewareSearchIndexer.indexing_is_enabled():
|
||||
# import here, because signal is registered at startup, but items in tasks are not yet able to be loaded
|
||||
from .tasks import update_search_index
|
||||
from contentstore.tasks import update_search_index
|
||||
|
||||
update_search_index.delay(unicode(course_key), datetime.now(UTC).isoformat())
|
||||
|
||||
@@ -66,7 +54,7 @@ def listen_for_library_update(sender, library_key, **kwargs): # pylint: disable
|
||||
|
||||
if LibrarySearchIndexer.indexing_is_enabled():
|
||||
# import here, because signal is registered at startup, but items in tasks are not yet able to be loaded
|
||||
from .tasks import update_library_index
|
||||
from contentstore.tasks import update_library_index
|
||||
|
||||
update_library_index.delay(unicode(library_key), datetime.now(UTC).isoformat())
|
||||
|
||||
14
cms/djangoapps/contentstore/signals/signals.py
Normal file
14
cms/djangoapps/contentstore/signals/signals.py
Normal file
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
Contentstore signals
|
||||
"""
|
||||
from django.dispatch import Signal
|
||||
|
||||
# Signal that indicates that a course grading policy has been updated.
|
||||
# This signal is generated when a grading policy change occurs within
|
||||
# modulestore for either course or subsection changes.
|
||||
GRADING_POLICY_CHANGED = Signal(
|
||||
providing_args=[
|
||||
'user_id', # Integer User ID
|
||||
'course_id', # Unicode string representing the course
|
||||
]
|
||||
)
|
||||
@@ -1,2 +0,0 @@
|
||||
""" will register signal handlers, moved out of __init__.py to ensure correct loading order post Django 1.7 """
|
||||
from . import signals # pylint: disable=unused-import
|
||||
@@ -44,7 +44,7 @@ from contentstore.courseware_index import (
|
||||
SearchIndexingError,
|
||||
CourseAboutSearchIndexer,
|
||||
)
|
||||
from contentstore.signals import listen_for_course_publish, listen_for_library_update
|
||||
from contentstore.signals.handlers import listen_for_course_publish, listen_for_library_update
|
||||
from contentstore.utils import reverse_course_url, reverse_usage_url
|
||||
from contentstore.tests.utils import CourseTestCase
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Unit tests for the gating feature in Studio
|
||||
"""
|
||||
from contentstore.signals import handle_item_deleted
|
||||
from contentstore.signals.handlers import handle_item_deleted
|
||||
from milestones.tests.utils import MilestonesTestCaseMixin
|
||||
from mock import patch
|
||||
from openedx.core.lib.gating import api as gating_api
|
||||
@@ -42,16 +42,16 @@ class TestHandleItemDeleted(ModuleStoreTestCase, MilestonesTestCaseMixin):
|
||||
gating_api.add_prerequisite(self.course.id, self.open_seq.location)
|
||||
gating_api.set_required_content(self.course.id, self.gated_seq.location, self.open_seq.location, 100)
|
||||
|
||||
@patch('contentstore.signals.gating_api.set_required_content')
|
||||
@patch('contentstore.signals.gating_api.remove_prerequisite')
|
||||
@patch('contentstore.signals.handlers.gating_api.set_required_content')
|
||||
@patch('contentstore.signals.handlers.gating_api.remove_prerequisite')
|
||||
def test_chapter_deleted(self, mock_remove_prereq, mock_set_required):
|
||||
""" Test gating milestone data is cleanup up when course content item is deleted """
|
||||
handle_item_deleted(usage_key=self.chapter.location, user_id=0)
|
||||
mock_remove_prereq.assert_called_with(self.open_seq.location)
|
||||
mock_set_required.assert_called_with(self.open_seq.location.course_key, self.open_seq.location, None, None)
|
||||
|
||||
@patch('contentstore.signals.gating_api.set_required_content')
|
||||
@patch('contentstore.signals.gating_api.remove_prerequisite')
|
||||
@patch('contentstore.signals.handlers.gating_api.set_required_content')
|
||||
@patch('contentstore.signals.handlers.gating_api.remove_prerequisite')
|
||||
def test_sequential_deleted(self, mock_remove_prereq, mock_set_required):
|
||||
""" Test gating milestone data is cleanup up when course content item is deleted """
|
||||
handle_item_deleted(usage_key=self.open_seq.location, user_id=0)
|
||||
|
||||
@@ -9,7 +9,7 @@ from pytz import UTC
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
from contentstore.signals import listen_for_course_publish
|
||||
from contentstore.signals.handlers import listen_for_course_publish
|
||||
|
||||
from edx_proctoring.api import (
|
||||
get_all_exams_for_course,
|
||||
|
||||
@@ -128,8 +128,8 @@ class TestSubsectionGating(CourseTestCase):
|
||||
self.assertEqual(resp['prereq_min_score'], 100)
|
||||
self.assertEqual(resp['visibility_state'], VisibilityState.gated)
|
||||
|
||||
@patch('contentstore.signals.gating_api.set_required_content')
|
||||
@patch('contentstore.signals.gating_api.remove_prerequisite')
|
||||
@patch('contentstore.signals.handlers.gating_api.set_required_content')
|
||||
@patch('contentstore.signals.handlers.gating_api.remove_prerequisite')
|
||||
def test_delete_item_signal_handler_called(self, mock_remove_prereq, mock_set_required):
|
||||
seq3 = ItemFactory.create(
|
||||
parent_location=self.chapter.location,
|
||||
|
||||
@@ -868,7 +868,8 @@ INSTALLED_APPS = (
|
||||
'django_nose',
|
||||
|
||||
# For CMS
|
||||
'contentstore',
|
||||
'contentstore.apps.ContentstoreConfig',
|
||||
|
||||
'openedx.core.djangoapps.contentserver',
|
||||
'course_creators',
|
||||
'openedx.core.djangoapps.external_auth',
|
||||
|
||||
Reference in New Issue
Block a user