<commit_before>"""
Module that provides a connection to the ModuleStore specified in the django settings.

Passes settings.MODULESTORE as kwargs to MongoModuleStore
"""

from __future__ import absolute_import

from importlib import import_module
from django.conf import settings
if not settings.configured:
    settings.configure()
from django.core.cache import get_cache, InvalidCacheBackendError
import django.dispatch
import django.utils

import re

from xmodule.util.django import get_current_request_hostname
import xmodule.modulestore  # pylint: disable=unused-import
from xmodule.modulestore.mixed import MixedModuleStore
from xmodule.modulestore.draft_and_published import BranchSettingMixin
from xmodule.contentstore.django import contentstore
import xblock.reference.plugins

# We may not always have the request_cache module available
try:
    from request_cache.middleware import RequestCache
    HAS_REQUEST_CACHE = True
except ImportError:
    HAS_REQUEST_CACHE = False

# We also may not always have the current request user (crum) module available
try:
    from xblock_django.user_service import DjangoXBlockUserService
    from crum import get_current_user
    HAS_USER_SERVICE = True
except ImportError:
    HAS_USER_SERVICE = False

ASSET_IGNORE_REGEX = getattr(settings, "ASSET_IGNORE_REGEX", r"(^\._.*$)|(^\.DS_Store$)|(^.*~$)")

class SignalHandler(object):
    course_published = django.dispatch.Signal(providing_args=["course_key", "version"])

    _mapping = {
        "course_published": course_published
    }

    def __init__(self, modulestore_class):
        self.modulestore_class = modulestore_class

    def send(self, signal_name, **kwargs):
        signal = self._mapping[signal_name]
        signal.send_robust(sender=self.modulestore_class, **kwargs)


def load_function(path):
    """
    Load a function by name.

    path is a string of the form "path.to.module.function"
    returns the imported python object `function` from `path.to.module`
    """
    module_path, _, name = path.rpartition('.')
    return getattr(import_module(module_path), name)

<commit_msg>Minor update to SignalHandler to better document how it should be used.<commit_after>"""
Module that provides a connection to the ModuleStore specified in the django settings.

Passes settings.MODULESTORE as kwargs to MongoModuleStore
"""

from __future__ import absolute_import

from importlib import import_module
from django.conf import settings
if not settings.configured:
    settings.configure()
from django.core.cache import get_cache, InvalidCacheBackendError
import django.dispatch
import django.utils

import re

from xmodule.util.django import get_current_request_hostname
import xmodule.modulestore  # pylint: disable=unused-import
from xmodule.modulestore.mixed import MixedModuleStore
from xmodule.modulestore.draft_and_published import BranchSettingMixin
from xmodule.contentstore.django import contentstore
import xblock.reference.plugins

# We may not always have the request_cache module available
try:
    from request_cache.middleware import RequestCache
    HAS_REQUEST_CACHE = True
except ImportError:
    HAS_REQUEST_CACHE = False

# We also may not always have the current request user (crum) module available
try:
    from xblock_django.user_service import DjangoXBlockUserService
    from crum import get_current_user
    HAS_USER_SERVICE = True
except ImportError:
    HAS_USER_SERVICE = False

ASSET_IGNORE_REGEX = getattr(settings, "ASSET_IGNORE_REGEX", r"(^\._.*$)|(^\.DS_Store$)|(^.*~$)")

class SignalHandler(object):
    """
    This class is to allow the modulestores to emit signals that can be caught
    by other parts of the Django application. If your app needs to do something
    every time a course is published (e.g. search indexing), you can listen for
    that event and kick off a celery task when it happens.

    To listen for a signal, do the following::

        from django.dispatch import receiver
        from celery.task import task
        from xmodule.modulestore.django import modulestore, SignalHandler

        @receiver(SignalHandler.course_published)
        def listen_for_course_publish(sender, course_key, **kwargs):
            do_my_expensive_update(course_key)

        @task()
        def do_my_expensive_update(course_key):
            # ...

    Things to note:

    1. We receive using the Django Signals mechanism.
    2. The sender is going to be the class of the modulestore sending it.
    3. Always have **kwargs in your signal handler, as new things may be added.
    4. The thing that listens for the signal lives in process, but should do
       almost no work. It's main job is to kick off the celery task that will
       do the actual work.

    """
    course_published = django.dispatch.Signal(providing_args=["course_key"])

    _mapping = {
        "course_published": course_published
    }

    def __init__(self, modulestore_class):
        self.modulestore_class = modulestore_class

    def send(self, signal_name, **kwargs):
        signal = self._mapping[signal_name]
        signal.send_robust(sender=self.modulestore_class, **kwargs)


def load_function(path):
    """
    Load a function by name.

    path is a string of the form "path.to.module.function"
    returns the imported python object `function` from `path.to.module`
    """
    module_path, _, name = path.rpartition('.')
    return getattr(import_module(module_path), name)


{'fraction_non_alphanumeric': 0.07112663113398272, 'fraction_numerical': 0.0007351589781290203, 'mean_word_length': 4.114661654135339, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1453410', 'n_tokens_mistral': 1565, 'n_tokens_neox': 1514, 'n_words': 506}