def test_request_cached_with_caches_despite_changing_wrapped_result(self):
        """
        Ensure that after caching a result, we always send it back, even if the underlying result changes.
        """
        RequestCache.clear_request_cache()

        to_be_wrapped = Mock()
        to_be_wrapped.side_effect = [1, 2, 3]
        self.assertEqual(to_be_wrapped.call_count, 0)

        def mock_wrapper(*args, **kwargs):
            """Simple wrapper to let us decorate our mock."""
            return to_be_wrapped(*args, **kwargs)

        wrapped = request_cached(mock_wrapper)
        result = wrapped()
        self.assertEqual(result, 1)
        self.assertEqual(to_be_wrapped.call_count, 1)

        result = wrapped()
        self.assertEqual(result, 1)
        self.assertEqual(to_be_wrapped.call_count, 1)

        direct_result = mock_wrapper()
        self.assertEqual(direct_result, 2)
        self.assertEqual(to_be_wrapped.call_count, 2)

        result = wrapped()
        self.assertEqual(result, 1)
        self.assertEqual(to_be_wrapped.call_count, 2)

        direct_result = mock_wrapper()
        self.assertEqual(direct_result, 3)
        self.assertEqual(to_be_wrapped.call_count, 3)
Beispiel #2
0
    def test_request_context_caching(self):
        """
        Test that the RequestContext is cached in the RequestCache.
        """
        with patch('edxmako.request_context.get_current_request',
                   return_value=None):
            # requestcontext should be None, because the cache isn't filled
            self.assertIsNone(get_template_request_context())

        with patch('edxmako.request_context.get_current_request',
                   return_value=self.request):
            # requestcontext should not be None, and should fill the cache
            self.assertIsNotNone(get_template_request_context())

        mock_get_current_request = Mock()
        with patch('edxmako.request_context.get_current_request',
                   mock_get_current_request):
            # requestcontext should not be None, because the cache is filled
            self.assertIsNotNone(get_template_request_context())
        mock_get_current_request.assert_not_called()

        RequestCache.clear_request_cache()

        with patch('edxmako.request_context.get_current_request',
                   return_value=None):
            # requestcontext should be None, because the cache isn't filled
            self.assertIsNone(get_template_request_context())
    def instrument_course_progress_render(
            self, course_width, enable_ccx, view_as_ccx,
            sql_queries, mongo_reads,
    ):
        """
        Renders the progress page, instrumenting Mongo reads and SQL queries.
        """
        course_key = self.setup_course(course_width, enable_ccx, view_as_ccx)

        # Switch to published-only mode to simulate the LMS
        with self.settings(MODULESTORE_BRANCH='published-only'):
            # Clear all caches before measuring
            for cache in settings.CACHES:
                caches[cache].clear()

            # Refill the metadata inheritance cache
            get_course_in_cache(course_key)

            # We clear the request cache to simulate a new request in the LMS.
            RequestCache.clear_request_cache()

            # Reset the list of provider classes, so that our django settings changes
            # can actually take affect.
            OverrideFieldData.provider_classes = None

            with self.assertNumQueries(sql_queries, using='default', table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
                with self.assertNumQueries(0, using='student_module_history'):
                    with self.assertMongoCallCount(mongo_reads):
                        with self.assertXBlockInstantiations(1):
                            self.grade_course(course_key)
    def test_request_cached_mixed_unicode_str_args(self):
        """
        Ensure that request_cached can work with mixed str and Unicode parameters.
        """
        RequestCache.clear_request_cache()

        def dummy_function(arg1, arg2):
            """
            A dummy function that expects an str and unicode arguments.
            """
            assert isinstance(arg1,
                              str), 'First parameter has to be of type `str`'
            assert isinstance(
                arg2, unicode), 'Second parameter has to be of type `unicode`'
            return True

        self.assertTrue(dummy_function('Hello', u'World'),
                        'Should be callable with ASCII chars')
        self.assertTrue(dummy_function('H∂llå', u'Wørld'),
                        'Should be callable with non-ASCII chars')

        wrapped = request_cached(dummy_function)

        self.assertTrue(wrapped('Hello', u'World'),
                        'Wrapper should handle ASCII only chars')
        self.assertTrue(wrapped('H∂llå', u'Wørld'),
                        'Wrapper should handle non-ASCII chars')
 def test_setting_override(self, is_enabled, override_choice, expected_result):
     RequestCache.clear_request_cache()
     self.set_waffle_course_override(override_choice, is_enabled)
     override_value = WaffleFlagCourseOverrideModel.override_value(
         self.WAFFLE_TEST_NAME, self.TEST_COURSE_KEY
     )
     self.assertEqual(override_value, expected_result)
Beispiel #6
0
    def test_request_cached_with_caches_despite_changing_wrapped_result(self):
        """
        Ensure that after caching a result, we always send it back, even if the underlying result changes.
        """
        RequestCache.clear_request_cache()

        to_be_wrapped = Mock()
        to_be_wrapped.side_effect = [1, 2, 3]
        self.assertEqual(to_be_wrapped.call_count, 0)

        def mock_wrapper(*args, **kwargs):
            """Simple wrapper to let us decorate our mock."""
            return to_be_wrapped(*args, **kwargs)

        wrapped = request_cached(mock_wrapper)
        result = wrapped()
        self.assertEqual(result, 1)
        self.assertEqual(to_be_wrapped.call_count, 1)

        result = wrapped()
        self.assertEqual(result, 1)
        self.assertEqual(to_be_wrapped.call_count, 1)

        direct_result = mock_wrapper()
        self.assertEqual(direct_result, 2)
        self.assertEqual(to_be_wrapped.call_count, 2)

        result = wrapped()
        self.assertEqual(result, 1)
        self.assertEqual(to_be_wrapped.call_count, 2)

        direct_result = mock_wrapper()
        self.assertEqual(direct_result, 3)
        self.assertEqual(to_be_wrapped.call_count, 3)
Beispiel #7
0
    def test_get_template_path(self):
        """
        Tests to make sure the get_template_path function works as expected.
        """
        # if the current site has associated SiteTheme then get_template_path should return the argument as is.
        with patch(
            "openedx.core.djangoapps.theming.helpers.current_request_has_associated_site_theme",
            Mock(return_value=True),
        ):
            with patch(
                "openedx.core.djangoapps.theming.helpers.microsite.is_request_in_microsite",
                Mock(return_value=True),
            ):
                with patch("microsite_configuration.microsite.TEMPLATES_BACKEND") as mock_microsite_backend:
                    mock_microsite_backend.get_template = Mock(return_value="/microsite/about.html")
                    self.assertEqual(theming_helpers.get_template_path("about.html"), "about.html")

        RequestCache.clear_request_cache()

        # if the current site does not have associated SiteTheme then get_template_path should return microsite override
        with patch(
            "openedx.core.djangoapps.theming.helpers.current_request_has_associated_site_theme",
            Mock(return_value=False),
        ):
            with patch(
                "openedx.core.djangoapps.theming.helpers.microsite.is_request_in_microsite",
                Mock(return_value=True),
            ):
                with patch("microsite_configuration.microsite.TEMPLATES_BACKEND") as mock_microsite_backend:
                    mock_microsite_backend.get_template_path = Mock(return_value="/microsite/about.html")
                    self.assertEqual(theming_helpers.get_template_path("about.html"), "/microsite/about.html")
 def test_setting_override_multiple_times(self):
     RequestCache.clear_request_cache()
     self.set_waffle_course_override(self.OVERRIDE_CHOICES.on)
     self.set_waffle_course_override(self.OVERRIDE_CHOICES.off)
     override_value = WaffleFlagCourseOverrideModel.override_value(
         self.WAFFLE_TEST_NAME, self.TEST_COURSE_KEY
     )
     self.assertEqual(override_value, self.OVERRIDE_CHOICES.off)
def lti_consumer_fields_editing_flag(course_id, enabled_for_course=False):
    """
    Yields CourseEditLTIFieldsEnabledFlag record for unit tests

    Arguments:
        course_id (CourseLocator): course locator to control this feature for.
        enabled_for_course (bool): whether feature is enabled for 'course_id'
    """
    RequestCache.clear_request_cache()
    CourseEditLTIFieldsEnabledFlag.objects.create(course_id=course_id, enabled=enabled_for_course)
    yield
    def assert_access_to_gated_content(self, user):
        """
        Verifies access to gated content for the given user is as expected.
        """
        # clear the request cache to flush any cached access results
        RequestCache.clear_request_cache()

        # access to gating content (seq1) remains constant
        self.assertTrue(bool(has_access(user, 'load', self.seq1, self.course.id)))

        # access to gated content (seq2) remains constant, access is prevented in SeqModule loading
        self.assertTrue(bool(has_access(user, 'load', self.seq2, self.course.id)))
    def assert_access_to_gated_content(self, user):
        """
        Verifies access to gated content for the given user is as expected.
        """
        # clear the request cache to flush any cached access results
        RequestCache.clear_request_cache()

        # access to gating content (seq1) remains constant
        self.assertTrue(
            bool(has_access(user, 'load', self.seq1, self.course.id)))

        # access to gated content (seq2) remains constant, access is prevented in SeqModule loading
        self.assertTrue(
            bool(has_access(user, 'load', self.seq2, self.course.id)))
Beispiel #12
0
def new_assets_page_feature_flags(global_flag,
                                  enabled_for_all_courses=False,
                                  course_id=None,
                                  enabled_for_course=False):
    """
    Most test cases will use a single call to this manager,
    as they need to set the global setting and the course-specific
    setting for a single course.
    """
    RequestCache.clear_request_cache()
    NewAssetsPageFlag.objects.create(
        enabled=global_flag, enabled_for_all_courses=enabled_for_all_courses)
    if course_id:
        CourseNewAssetsPageFlag.objects.create(course_id=course_id,
                                               enabled=enabled_for_course)
    yield
Beispiel #13
0
    def clear_caches(cls):
        """
        Clear all of the caches defined in settings.CACHES.
        """
        # N.B. As of 2016-04-20, Django won't return any caches
        # from django.core.cache.caches.all() that haven't been
        # accessed using caches[name] previously, so we loop
        # over our list of overridden caches, instead.
        for cache in settings.CACHES:
            caches[cache].clear()

        # The sites framework caches in a module-level dictionary.
        # Clear that.
        sites.models.SITE_CACHE.clear()

        RequestCache.clear_request_cache()
Beispiel #14
0
def persistent_grades_feature_flags(global_flag,
                                    enabled_for_all_courses=False,
                                    course_id=None,
                                    enabled_for_course=False):
    """
    Most test cases will use a single call to this manager,
    as they need to set the global setting and the course-specific
    setting for a single course.
    """
    RequestCache.clear_request_cache()
    PersistentGradesEnabledFlag.objects.create(
        enabled=global_flag, enabled_for_all_courses=enabled_for_all_courses)
    if course_id:
        CoursePersistentGradesFlag.objects.create(course_id=course_id,
                                                  enabled=enabled_for_course)
    yield
Beispiel #15
0
def persistent_grades_feature_flags(
        global_flag,
        enabled_for_all_courses=False,
        course_id=None,
        enabled_for_course=False
):
    """
    Most test cases will use a single call to this manager,
    as they need to set the global setting and the course-specific
    setting for a single course.
    """
    RequestCache.clear_request_cache()
    PersistentGradesEnabledFlag.objects.create(enabled=global_flag, enabled_for_all_courses=enabled_for_all_courses)
    if course_id:
        CoursePersistentGradesFlag.objects.create(course_id=course_id, enabled=enabled_for_course)
    yield
Beispiel #16
0
 def check_question_author(user, content):
     """ Check if the given user is the author of the original question for both threads and comments. """
     if not content:
         return False
     try:
         request_cache_dict = RequestCache.get_request_cache().data
         if content["type"] == "thread":
             cache_key = "django_comment_client.permissions._check_condition.check_question_author.{}.{}".format(
                 user.id, content['id']
             )
             if cache_key in request_cache_dict:
                 return request_cache_dict[cache_key]
             else:
                 result = content["thread_type"] == "question" and content["user_id"] == str(user.id)
                 request_cache_dict[cache_key] = result
                 return result
         else:
             cache_key = "django_comment_client.permissions._check_condition.check_question_author.{}.{}".format(
                 user.id, content['thread_id']
             )
             if cache_key in request_cache_dict:
                 return request_cache_dict[cache_key]
             else:
                 # make the now-unavoidable comments service query
                 thread = Thread(id=content['thread_id']).to_dict()
                 return check_question_author(user, thread)
     except KeyError:
         return False
Beispiel #17
0
def new_assets_page_feature_flags(
        global_flag,
        enabled_for_all_courses=False,
        course_id=None,
        enabled_for_course=False
):
    """
    Most test cases will use a single call to this manager,
    as they need to set the global setting and the course-specific
    setting for a single course.
    """
    RequestCache.clear_request_cache()
    NewAssetsPageFlag.objects.create(enabled=global_flag, enabled_for_all_courses=enabled_for_all_courses)
    if course_id:
        CourseNewAssetsPageFlag.objects.create(course_id=course_id, enabled=enabled_for_course)
    yield
Beispiel #18
0
 def check_question_author(user, content):
     """ Check if the given user is the author of the original question for both threads and comments. """
     if not content:
         return False
     try:
         request_cache_dict = RequestCache.get_request_cache().data
         if content["type"] == "thread":
             cache_key = "django_comment_client.permissions._check_condition.check_question_author.{}.{}".format(
                 user.id, content['id'])
             if cache_key in request_cache_dict:
                 return request_cache_dict[cache_key]
             else:
                 result = content["thread_type"] == "question" and content[
                     "user_id"] == str(user.id)
                 request_cache_dict[cache_key] = result
                 return result
         else:
             cache_key = "django_comment_client.permissions._check_condition.check_question_author.{}.{}".format(
                 user.id, content['thread_id'])
             if cache_key in request_cache_dict:
                 return request_cache_dict[cache_key]
             else:
                 # make the now-unavoidable comments service query
                 thread = Thread(id=content['thread_id']).to_dict()
                 return check_question_author(user, thread)
     except KeyError:
         return False
Beispiel #19
0
 def check_team_member(user, content):
     """
     If the content has a commentable_id, verifies that either it is not associated with a team,
     or if it is, that the user is a member of that team.
     """
     if not content:
         return False
     try:
         commentable_id = content['commentable_id']
         request_cache_dict = RequestCache.get_request_cache().data
         cache_key = u"django_comment_client.check_team_member.{}.{}".format(
             user.id, commentable_id)
         if cache_key in request_cache_dict:
             return request_cache_dict[cache_key]
         team = get_team(commentable_id)
         if team is None:
             passes_condition = True
         else:
             passes_condition = team.users.filter(id=user.id).exists()
         request_cache_dict[cache_key] = passes_condition
     except KeyError:
         # We do not expect KeyError in production-- it usually indicates an improper test mock.
         logging.warning("Did not find key commentable_id in content.")
         passes_condition = False
     return passes_condition
    def clear_caches(cls):
        """
        Clear all of the caches defined in settings.CACHES.
        """
        # N.B. As of 2016-04-20, Django won't return any caches
        # from django.core.cache.caches.all() that haven't been
        # accessed using caches[name] previously, so we loop
        # over our list of overridden caches, instead.
        for cache in settings.CACHES:
            caches[cache].clear()

        # The sites framework caches in a module-level dictionary.
        # Clear that.
        sites.models.SITE_CACHE.clear()

        RequestCache.clear_request_cache()
Beispiel #21
0
def get_current_request():
    """
    Return current request instance.

    Returns:
         (HttpRequest): returns current request
    """
    return RequestCache.get_current_request()
Beispiel #22
0
def get_current_request():
    """
    Return current request instance.

    Returns:
         (HttpRequest): returns current request
    """
    return RequestCache.get_current_request()
Beispiel #23
0
    def test_request_cached_with_changing_kwargs(self):
        """
        Ensure that calling a decorated function with different keyword arguments
        will not use a cached value invoked by a previous call with different arguments.
        """
        RequestCache.clear_request_cache()

        to_be_wrapped = Mock()
        to_be_wrapped.side_effect = [1, 2, 3, 4, 5, 6]
        self.assertEqual(to_be_wrapped.call_count, 0)

        def mock_wrapper(*args, **kwargs):
            """Simple wrapper to let us decorate our mock."""
            return to_be_wrapped(*args, **kwargs)

        wrapped = request_cached(mock_wrapper)

        # This will be a miss, and make an underlying call.
        result = wrapped(1, foo=1)
        self.assertEqual(result, 1)
        self.assertEqual(to_be_wrapped.call_count, 1)

        # This will be a miss, and make an underlying call.
        result = wrapped(2, foo=2)
        self.assertEqual(result, 2)
        self.assertEqual(to_be_wrapped.call_count, 2)

        # This is bypass of the decorator.
        direct_result = mock_wrapper(3, foo=3)
        self.assertEqual(direct_result, 3)
        self.assertEqual(to_be_wrapped.call_count, 3)

        # These will be hits, and not make an underlying call.
        result = wrapped(1, foo=1)
        self.assertEqual(result, 1)
        self.assertEqual(to_be_wrapped.call_count, 3)

        result = wrapped(2, foo=2)
        self.assertEqual(result, 2)
        self.assertEqual(to_be_wrapped.call_count, 3)

        # Since we're changing foo, this will be a miss.
        result = wrapped(2, foo=5)
        self.assertEqual(result, 4)
        self.assertEqual(to_be_wrapped.call_count, 4)
    def test_request_cached_with_changing_kwargs(self):
        """
        Ensure that calling a decorated function with different keyword arguments
        will not use a cached value invoked by a previous call with different arguments.
        """
        RequestCache.clear_request_cache()

        to_be_wrapped = Mock()
        to_be_wrapped.side_effect = [1, 2, 3, 4, 5, 6]
        self.assertEqual(to_be_wrapped.call_count, 0)

        def mock_wrapper(*args, **kwargs):
            """Simple wrapper to let us decorate our mock."""
            return to_be_wrapped(*args, **kwargs)

        wrapped = request_cached(mock_wrapper)

        # This will be a miss, and make an underlying call.
        result = wrapped(1, foo=1)
        self.assertEqual(result, 1)
        self.assertEqual(to_be_wrapped.call_count, 1)

        # This will be a miss, and make an underlying call.
        result = wrapped(2, foo=2)
        self.assertEqual(result, 2)
        self.assertEqual(to_be_wrapped.call_count, 2)

        # This is bypass of the decorator.
        direct_result = mock_wrapper(3, foo=3)
        self.assertEqual(direct_result, 3)
        self.assertEqual(to_be_wrapped.call_count, 3)

        # These will be hits, and not make an underlying call.
        result = wrapped(1, foo=1)
        self.assertEqual(result, 1)
        self.assertEqual(to_be_wrapped.call_count, 3)

        result = wrapped(2, foo=2)
        self.assertEqual(result, 2)
        self.assertEqual(to_be_wrapped.call_count, 3)

        # Since we're changing foo, this will be a miss.
        result = wrapped(2, foo=5)
        self.assertEqual(result, 4)
        self.assertEqual(to_be_wrapped.call_count, 4)
Beispiel #25
0
def get_request_user():
    """
    Helper to get the authenticated user from the current HTTP request (if
    applicable).

    If the requester of an unenrollment is not the same person as the student
    being unenrolled, we authenticate to the commerce service as the requester.
    """
    request = RequestCache.get_current_request()
    return getattr(request, 'user', None)
Beispiel #26
0
    def dump_courses_to_neo4j(self, credentials, override_cache=False):
        """
        Method that iterates through a list of courses in a modulestore,
        serializes them, then submits tasks to write them to neo4j.
        Arguments:
            credentials (dict): the necessary credentials to connect
              to neo4j and create a py2neo `Graph` object
            override_cache: serialize the courses even if they'be been recently
                serialized

        Returns: two lists--one of the courses that were successfully written
            to neo4j and one of courses that were not.
        """

        total_number_of_courses = len(self.course_keys)

        submitted_courses = []
        skipped_courses = []

        graph = authenticate_and_create_graph(credentials)

        for index, course_key in enumerate(self.course_keys):
            # first, clear the request cache to prevent memory leaks
            RequestCache.clear_request_cache()

            log.info(
                "Now submitting %s for export to neo4j: course %d of %d total courses",
                course_key,
                index + 1,
                total_number_of_courses,
            )

            if not (override_cache or should_dump_course(course_key, graph)):
                log.info("skipping submitting %s, since it hasn't changed",
                         course_key)
                skipped_courses.append(six.text_type(course_key))
                continue

            dump_course_to_neo4j.apply_async(
                args=[six.text_type(course_key), credentials], )
            submitted_courses.append(six.text_type(course_key))

        return submitted_courses, skipped_courses
Beispiel #27
0
    def dump_courses_to_neo4j(self, credentials, override_cache=False):
        """
        Method that iterates through a list of courses in a modulestore,
        serializes them, then submits tasks to write them to neo4j.
        Arguments:
            credentials (dict): the necessary credentials to connect
              to neo4j and create a py2neo `Graph` object
            override_cache: serialize the courses even if they'be been recently
                serialized

        Returns: two lists--one of the courses that were successfully written
            to neo4j and one of courses that were not.
        """

        total_number_of_courses = len(self.course_keys)

        submitted_courses = []
        skipped_courses = []

        graph = authenticate_and_create_graph(credentials)

        for index, course_key in enumerate(self.course_keys):
            # first, clear the request cache to prevent memory leaks
            RequestCache.clear_request_cache()

            log.info(
                "Now submitting %s for export to neo4j: course %d of %d total courses",
                course_key,
                index + 1,
                total_number_of_courses,
            )

            if not (override_cache or should_dump_course(course_key, graph)):
                log.info("skipping submitting %s, since it hasn't changed", course_key)
                skipped_courses.append(six.text_type(course_key))
                continue

            dump_course_to_neo4j.apply_async(
                args=[six.text_type(course_key), credentials],
            )
            submitted_courses.append(six.text_type(course_key))

        return submitted_courses, skipped_courses
Beispiel #28
0
    def test_request_cached_with_none_result(self):
        """
        Ensure that calling a decorated function that returns None
        properly caches the result and doesn't recall the underlying
        function.
        """
        RequestCache.clear_request_cache()

        to_be_wrapped = Mock()
        to_be_wrapped.side_effect = [None, None, None, 1, 1]
        self.assertEqual(to_be_wrapped.call_count, 0)

        def mock_wrapper(*args, **kwargs):
            """Simple wrapper to let us decorate our mock."""
            return to_be_wrapped(*args, **kwargs)

        wrapped = request_cached(mock_wrapper)

        # This will be a miss, and make an underlying call.
        result = wrapped(1)
        self.assertEqual(result, None)
        self.assertEqual(to_be_wrapped.call_count, 1)

        # This will be a miss, and make an underlying call.
        result = wrapped(2)
        self.assertEqual(result, None)
        self.assertEqual(to_be_wrapped.call_count, 2)

        # This is bypass of the decorator.
        direct_result = mock_wrapper(3)
        self.assertEqual(direct_result, None)
        self.assertEqual(to_be_wrapped.call_count, 3)

        # These will be hits, and not make an underlying call.
        result = wrapped(1)
        self.assertEqual(result, None)
        self.assertEqual(to_be_wrapped.call_count, 3)

        result = wrapped(2)
        self.assertEqual(result, None)
        self.assertEqual(to_be_wrapped.call_count, 3)
    def test_request_cached_with_none_result(self):
        """
        Ensure that calling a decorated function that returns None
        properly caches the result and doesn't recall the underlying
        function.
        """
        RequestCache.clear_request_cache()

        to_be_wrapped = Mock()
        to_be_wrapped.side_effect = [None, None, None, 1, 1]
        self.assertEqual(to_be_wrapped.call_count, 0)

        def mock_wrapper(*args, **kwargs):
            """Simple wrapper to let us decorate our mock."""
            return to_be_wrapped(*args, **kwargs)

        wrapped = request_cached(mock_wrapper)

        # This will be a miss, and make an underlying call.
        result = wrapped(1)
        self.assertEqual(result, None)
        self.assertEqual(to_be_wrapped.call_count, 1)

        # This will be a miss, and make an underlying call.
        result = wrapped(2)
        self.assertEqual(result, None)
        self.assertEqual(to_be_wrapped.call_count, 2)

        # This is bypass of the decorator.
        direct_result = mock_wrapper(3)
        self.assertEqual(direct_result, None)
        self.assertEqual(to_be_wrapped.call_count, 3)

        # These will be hits, and not make an underlying call.
        result = wrapped(1)
        self.assertEqual(result, None)
        self.assertEqual(to_be_wrapped.call_count, 3)

        result = wrapped(2)
        self.assertEqual(result, None)
        self.assertEqual(to_be_wrapped.call_count, 3)
Beispiel #30
0
def has_permission(user, permission, course_id=None):
    assert isinstance(course_id, (NoneType, CourseKey))
    request_cache_dict = RequestCache.get_request_cache().data
    cache_key = "django_comment_client.permissions.has_permission.all_permissions.{}.{}".format(
        user.id, course_id)
    if cache_key in request_cache_dict:
        all_permissions = request_cache_dict[cache_key]
    else:
        all_permissions = all_permissions_for_user_in_course(user, course_id)
        request_cache_dict[cache_key] = all_permissions

    return permission in all_permissions
Beispiel #31
0
    def test_request_cached_mixed_unicode_str_args(self):
        """
        Ensure that request_cached can work with mixed str and Unicode parameters.
        """
        RequestCache.clear_request_cache()

        def dummy_function(arg1, arg2):
            """
            A dummy function that expects an str and unicode arguments.
            """
            assert isinstance(arg1, str), 'First parameter has to be of type `str`'
            assert isinstance(arg2, unicode), 'Second parameter has to be of type `unicode`'
            return True

        self.assertTrue(dummy_function('Hello', u'World'), 'Should be callable with ASCII chars')
        self.assertTrue(dummy_function('H∂llå', u'Wørld'), 'Should be callable with non-ASCII chars')

        wrapped = request_cached(dummy_function)

        self.assertTrue(wrapped('Hello', u'World'), 'Wrapper should handle ASCII only chars')
        self.assertTrue(wrapped('H∂llå', u'Wørld'), 'Wrapper should handle non-ASCII chars')
Beispiel #32
0
def has_permission(user, permission, course_id=None):
    assert isinstance(course_id, (NoneType, CourseKey))
    request_cache_dict = RequestCache.get_request_cache().data
    cache_key = "django_comment_client.permissions.has_permission.all_permissions.{}.{}".format(
        user.id, course_id
    )
    if cache_key in request_cache_dict:
        all_permissions = request_cache_dict[cache_key]
    else:
        all_permissions = all_permissions_for_user_in_course(user, course_id)
        request_cache_dict[cache_key] = all_permissions

    return permission in all_permissions
Beispiel #33
0
    def test_request_cached_miss_and_then_hit(self):
        """
        Ensure that after a cache miss, we fill the cache and can hit it.
        """
        RequestCache.clear_request_cache()

        to_be_wrapped = Mock()
        to_be_wrapped.return_value = 42
        self.assertEqual(to_be_wrapped.call_count, 0)

        def mock_wrapper(*args, **kwargs):
            """Simple wrapper to let us decorate our mock."""
            return to_be_wrapped(*args, **kwargs)

        wrapped = request_cached(mock_wrapper)
        result = wrapped()
        self.assertEqual(result, 42)
        self.assertEqual(to_be_wrapped.call_count, 1)

        result = wrapped()
        self.assertEqual(result, 42)
        self.assertEqual(to_be_wrapped.call_count, 1)
    def test_request_cached_miss_and_then_hit(self):
        """
        Ensure that after a cache miss, we fill the cache and can hit it.
        """
        RequestCache.clear_request_cache()

        to_be_wrapped = Mock()
        to_be_wrapped.return_value = 42
        self.assertEqual(to_be_wrapped.call_count, 0)

        def mock_wrapper(*args, **kwargs):
            """Simple wrapper to let us decorate our mock."""
            return to_be_wrapped(*args, **kwargs)

        wrapped = request_cached(mock_wrapper)
        result = wrapped()
        self.assertEqual(result, 42)
        self.assertEqual(to_be_wrapped.call_count, 1)

        result = wrapped()
        self.assertEqual(result, 42)
        self.assertEqual(to_be_wrapped.call_count, 1)
Beispiel #35
0
    def _bookmarks_cache(self, course_key, fetch=False):
        """
        Return the user's bookmarks cache for a particular course.

        Arguments:
            course_key (CourseKey): course_key of the course whose bookmarks cache should be returned.
            fetch (Bool): if the bookmarks should be fetched and cached if they already aren't.
        """
        store = modulestore()
        course_key = store.fill_in_run(course_key)
        if course_key.run is None:
            return []
        cache_key = CACHE_KEY_TEMPLATE.format(self._user.id, course_key)

        bookmarks_cache = RequestCache.get_request_cache().data.get(cache_key, None)
        if bookmarks_cache is None and fetch is True:
            bookmarks_cache = api.get_bookmarks(
                self._user, course_key=course_key, fields=DEFAULT_FIELDS
            )
            RequestCache.get_request_cache().data[cache_key] = bookmarks_cache

        return bookmarks_cache
Beispiel #36
0
    def _bookmarks_cache(self, course_key, fetch=False):
        """
        Return the user's bookmarks cache for a particular course.

        Arguments:
            course_key (CourseKey): course_key of the course whose bookmarks cache should be returned.
            fetch (Bool): if the bookmarks should be fetched and cached if they already aren't.
        """
        store = modulestore()
        course_key = store.fill_in_run(course_key)
        if course_key.run is None:
            return []
        cache_key = CACHE_KEY_TEMPLATE.format(self._user.id, course_key)

        bookmarks_cache = RequestCache.get_request_cache().data.get(
            cache_key, None)
        if bookmarks_cache is None and fetch is True:
            bookmarks_cache = api.get_bookmarks(self._user,
                                                course_key=course_key,
                                                fields=DEFAULT_FIELDS)
            RequestCache.get_request_cache().data[cache_key] = bookmarks_cache

        return bookmarks_cache
Beispiel #37
0
    def test_request_context_caching(self):
        """
        Test that the RequestContext is cached in the RequestCache.
        """
        with patch('edxmako.request_context.get_current_request', return_value=None):
            # requestcontext should be None, because the cache isn't filled
            self.assertIsNone(get_template_request_context())

        with patch('edxmako.request_context.get_current_request', return_value=self.request):
            # requestcontext should not be None, and should fill the cache
            self.assertIsNotNone(get_template_request_context())

        mock_get_current_request = Mock()
        with patch('edxmako.request_context.get_current_request', mock_get_current_request):
            # requestcontext should not be None, because the cache is filled
            self.assertIsNotNone(get_template_request_context())
        mock_get_current_request.assert_not_called()

        RequestCache.clear_request_cache()

        with patch('edxmako.request_context.get_current_request', return_value=None):
            # requestcontext should be None, because the cache isn't filled
            self.assertIsNone(get_template_request_context())
Beispiel #38
0
    def instrument_course_progress_render(
        self,
        course_width,
        enable_ccx,
        view_as_ccx,
        sql_queries,
        mongo_reads,
    ):
        """
        Renders the progress page, instrumenting Mongo reads and SQL queries.
        """
        course_key = self.setup_course(course_width, enable_ccx, view_as_ccx)

        # Switch to published-only mode to simulate the LMS
        with self.settings(MODULESTORE_BRANCH='published-only'):
            # Clear all caches before measuring
            for cache in settings.CACHES:
                caches[cache].clear()

            # Refill the metadata inheritance cache
            get_course_in_cache(course_key)

            # We clear the request cache to simulate a new request in the LMS.
            RequestCache.clear_request_cache()

            # Reset the list of provider classes, so that our django settings changes
            # can actually take affect.
            OverrideFieldData.provider_classes = None

            with self.assertNumQueries(
                    sql_queries,
                    using='default',
                    table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
                with self.assertNumQueries(0, using='student_module_history'):
                    with self.assertMongoCallCount(mongo_reads):
                        with self.assertXBlockInstantiations(1):
                            self.grade_course(course_key)
Beispiel #39
0
    def __init__(self, **kwargs):
        request_cache_dict = RequestCache.get_request_cache().data
        store = modulestore()

        services = kwargs.setdefault('services', {})
        services['completion'] = CompletionService(
            user=kwargs.get('user'), course_key=kwargs.get('course_id'))
        services['fs'] = xblock.reference.plugins.FSService()
        services['i18n'] = ModuleI18nService
        services['library_tools'] = LibraryToolsService(store)
        services['partitions'] = PartitionService(
            course_id=kwargs.get('course_id'), cache=request_cache_dict)
        services['settings'] = SettingsService()
        services['user_tags'] = UserTagsService(self)
        if badges_enabled():
            services['badging'] = BadgingService(
                course_id=kwargs.get('course_id'), modulestore=store)
        self.request_token = kwargs.pop('request_token', None)
        super(LmsModuleSystem, self).__init__(**kwargs)
Beispiel #40
0
    def __init__(self, **kwargs):
        request_cache_dict = RequestCache.get_request_cache().data
        store = modulestore()

        services = kwargs.setdefault('services', {})
        services['completion'] = CompletionService(user=kwargs.get('user'), course_key=kwargs.get('course_id'))
        services['fs'] = xblock.reference.plugins.FSService()
        services['i18n'] = ModuleI18nService
        services['library_tools'] = LibraryToolsService(store)
        services['partitions'] = PartitionService(
            course_id=kwargs.get('course_id'),
            cache=request_cache_dict
        )
        services['settings'] = SettingsService()
        services['user_tags'] = UserTagsService(self)
        if badges_enabled():
            services['badging'] = BadgingService(course_id=kwargs.get('course_id'), modulestore=store)
        self.request_token = kwargs.pop('request_token', None)
        super(LmsModuleSystem, self).__init__(**kwargs)
    def _providers_for_block(cls, block):
        """
        Computes a list of enabled providers based on the given XBlock.
        The result is cached per request to avoid the overhead incurred
        by filtering override providers hundreds of times.

        Arguments:
            block: An XBlock
        """
        course_id = unicode(block.location.course_key)
        cache_key = ENABLED_MODULESTORE_OVERRIDE_PROVIDERS_KEY.format(course_id=course_id)

        request_cache = RequestCache.get_request_cache()
        enabled_providers = request_cache.data.get(cache_key)

        if enabled_providers is None:
            enabled_providers = [
                provider_class for provider_class in cls.provider_classes if provider_class.enabled_for(block)
            ]
            request_cache.data[cache_key] = enabled_providers

        return enabled_providers
    def _providers_for_course(cls, course):
        """
        Return a filtered list of enabled providers based
        on the course passed in. Cache this result per request to avoid
        needing to call the provider filter api hundreds of times.

        Arguments:
            course: The course XBlock
        """
        request_cache = RequestCache.get_request_cache()
        if course is None:
            cache_key = ENABLED_OVERRIDE_PROVIDERS_KEY.format(course_id='None')
        else:
            cache_key = ENABLED_OVERRIDE_PROVIDERS_KEY.format(course_id=unicode(course.id))
        enabled_providers = request_cache.data.get(cache_key, NOTSET)
        if enabled_providers == NOTSET:
            enabled_providers = tuple(
                (provider_class for provider_class in cls.provider_classes if provider_class.enabled_for(course))
            )
            request_cache.data[cache_key] = enabled_providers

        return enabled_providers
Beispiel #43
0
 def check_team_member(user, content):
     """
     If the content has a commentable_id, verifies that either it is not associated with a team,
     or if it is, that the user is a member of that team.
     """
     if not content:
         return False
     try:
         commentable_id = content['commentable_id']
         request_cache_dict = RequestCache.get_request_cache().data
         cache_key = u"django_comment_client.check_team_member.{}.{}".format(user.id, commentable_id)
         if cache_key in request_cache_dict:
             return request_cache_dict[cache_key]
         team = get_team(commentable_id)
         if team is None:
             passes_condition = True
         else:
             passes_condition = team.users.filter(id=user.id).exists()
         request_cache_dict[cache_key] = passes_condition
     except KeyError:
         # We do not expect KeyError in production-- it usually indicates an improper test mock.
         logging.warning("Did not find key commentable_id in content.")
         passes_condition = False
     return passes_condition
Beispiel #44
0
def invalidate_credit_requirement_cache(sender, **kwargs):   # pylint: disable=unused-argument
    """Invalidate the cache of credit requirements. """
    RequestCache.clear_request_cache(name=CreditRequirement.CACHE_NAMESPACE)
Beispiel #45
0
def invalidate_course_mode_cache(sender, **kwargs):  # pylint: disable=unused-argument
    """Invalidate the cache of course modes. """
    RequestCache.clear_request_cache(name=CourseMode.CACHE_NAMESPACE)
Beispiel #46
0
def invalidate_credit_requirement_cache(sender, **kwargs):  # pylint: disable=unused-argument
    """Invalidate the cache of credit requirements. """
    RequestCache.clear_request_cache(name=CreditRequirement.CACHE_NAMESPACE)
Beispiel #47
0
def invalidate_course_mode_cache(sender, **kwargs):   # pylint: disable=unused-argument
    """Invalidate the cache of course modes. """
    RequestCache.clear_request_cache(name=CourseMode.CACHE_NAMESPACE)
Beispiel #48
0
def create_modulestore_instance(
        engine,
        content_store,
        doc_store_config,
        options,
        i18n_service=None,
        fs_service=None,
        user_service=None,
        signal_handler=None,
):
    """
    This will return a new instance of a modulestore given an engine and options
    """
    # Import is placed here to avoid model import at project startup.
    import xblock.reference.plugins

    class_ = load_function(engine)

    _options = {}
    _options.update(options)

    FUNCTION_KEYS = ['render_template']
    for key in FUNCTION_KEYS:
        if key in _options and isinstance(_options[key], basestring):
            _options[key] = load_function(_options[key])

    request_cache = RequestCache.get_request_cache()

    try:
        metadata_inheritance_cache = caches['mongo_metadata_inheritance']
    except InvalidCacheBackendError:
        metadata_inheritance_cache = caches['default']

    if issubclass(class_, MixedModuleStore):
        _options['create_modulestore_instance'] = create_modulestore_instance

    if issubclass(class_, BranchSettingMixin):
        _options['branch_setting_func'] = _get_modulestore_branch_setting

    if HAS_USER_SERVICE and not user_service:
        xb_user_service = DjangoXBlockUserService(get_current_user())
    else:
        xb_user_service = None

    xblock_field_data_wrappers = [load_function(path) for path in settings.XBLOCK_FIELD_DATA_WRAPPERS]

    def fetch_disabled_xblock_types():
        """
        Get the disabled xblock names, using the request_cache if possible to avoid hitting
        a database every time the list is needed.
        """
        # If the import could not be loaded, return an empty list.
        if disabled_xblocks is None:
            return []

        if request_cache:
            if 'disabled_xblock_types' not in request_cache.data:
                request_cache.data['disabled_xblock_types'] = [block.name for block in disabled_xblocks()]
            return request_cache.data['disabled_xblock_types']
        else:
            disabled_xblock_types = [block.name for block in disabled_xblocks()]

        return disabled_xblock_types

    return class_(
        contentstore=content_store,
        metadata_inheritance_cache_subsystem=metadata_inheritance_cache,
        request_cache=request_cache,
        xblock_mixins=getattr(settings, 'XBLOCK_MIXINS', ()),
        xblock_select=getattr(settings, 'XBLOCK_SELECT_FUNCTION', None),
        xblock_field_data_wrappers=xblock_field_data_wrappers,
        disabled_xblock_types=fetch_disabled_xblock_types,
        doc_store_config=doc_store_config,
        i18n_service=i18n_service or ModuleI18nService,
        fs_service=fs_service or xblock.reference.plugins.FSService(),
        user_service=user_service or xb_user_service,
        signal_handler=signal_handler or SignalHandler(class_),
        **_options
    )
Beispiel #49
0
 def setUp(self):
     super(TestCourseWaffleFlag, self).setUp()
     request = RequestFactory().request()
     crum.set_current_request(request)
     RequestCache.clear_request_cache()
Beispiel #50
0
def create_modulestore_instance(
    engine,
    content_store,
    doc_store_config,
    options,
    i18n_service=None,
    fs_service=None,
    user_service=None,
    signal_handler=None,
):
    """
    This will return a new instance of a modulestore given an engine and options
    """
    # Import is placed here to avoid model import at project startup.
    import xblock.reference.plugins

    class_ = load_function(engine)

    _options = {}
    _options.update(options)

    FUNCTION_KEYS = ['render_template']
    for key in FUNCTION_KEYS:
        if key in _options and isinstance(_options[key], basestring):
            _options[key] = load_function(_options[key])

    request_cache = RequestCache.get_request_cache()

    try:
        metadata_inheritance_cache = caches['mongo_metadata_inheritance']
    except InvalidCacheBackendError:
        metadata_inheritance_cache = caches['default']

    if issubclass(class_, MixedModuleStore):
        _options['create_modulestore_instance'] = create_modulestore_instance

    if issubclass(class_, BranchSettingMixin):
        _options['branch_setting_func'] = _get_modulestore_branch_setting

    if HAS_USER_SERVICE and not user_service:
        xb_user_service = DjangoXBlockUserService(get_current_user())
    else:
        xb_user_service = None

    xblock_field_data_wrappers = [
        load_function(path) for path in settings.XBLOCK_FIELD_DATA_WRAPPERS
    ]

    def fetch_disabled_xblock_types():
        """
        Get the disabled xblock names, using the request_cache if possible to avoid hitting
        a database every time the list is needed.
        """
        # If the import could not be loaded, return an empty list.
        if disabled_xblocks is None:
            return []

        if request_cache:
            if 'disabled_xblock_types' not in request_cache.data:
                request_cache.data['disabled_xblock_types'] = [
                    block.name for block in disabled_xblocks()
                ]
            return request_cache.data['disabled_xblock_types']
        else:
            disabled_xblock_types = [
                block.name for block in disabled_xblocks()
            ]

        return disabled_xblock_types

    return class_(
        contentstore=content_store,
        metadata_inheritance_cache_subsystem=metadata_inheritance_cache,
        request_cache=request_cache,
        xblock_mixins=getattr(settings, 'XBLOCK_MIXINS', ()),
        xblock_select=getattr(settings, 'XBLOCK_SELECT_FUNCTION', None),
        xblock_field_data_wrappers=xblock_field_data_wrappers,
        disabled_xblock_types=fetch_disabled_xblock_types,
        doc_store_config=doc_store_config,
        i18n_service=i18n_service or ModuleI18nService,
        fs_service=fs_service or xblock.reference.plugins.FSService(),
        user_service=user_service or xb_user_service,
        signal_handler=signal_handler or SignalHandler(class_),
        **_options)
Beispiel #51
0
def invalidate_verified_track_cache(sender, **kwargs):   # pylint: disable=unused-argument
    """Invalidate the cache of VerifiedTrackCohortedCourse. """
    RequestCache.clear_request_cache(name=VerifiedTrackCohortedCourse.CACHE_NAMESPACE)
Beispiel #52
0
def invalidate_verified_track_cache(sender, **kwargs):   # pylint: disable=unused-argument
    """Invalidate the cache of VerifiedTrackCohortedCourse. """
    RequestCache.clear_request_cache(name=VerifiedTrackCohortedCourse.CACHE_NAMESPACE)
 def setUp(self):
     super(TestCourseWaffleFlag, self).setUp()
     request = RequestFactory().request()
     crum.set_current_request(request)
     RequestCache.clear_request_cache()
Beispiel #54
0
 def setUp(self):
     super(OverrideWaffleFlagTests, self).setUp()
     request = RequestFactory().request()
     self.addCleanup(crum.set_current_request, None)
     crum.set_current_request(request)
     RequestCache.clear_request_cache()