def test_rerandomization_set(self):
     descriptor = ItemFactory.create(
         category='problem',
         data=self.problem_xml,
         display_name='Option Response Problem2',
         rerandomize='always',
     )
     location = descriptor.location
     field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
         self.course.id,
         self.user,
         descriptor
     )
     module = render.get_module(
         self.user,
         self.request,
         location,
         field_data_cache,
     )
     result_fragment = module.render(STUDENT_VIEW)
     self.assertIn('Staff Analytics Info', result_fragment.content)
     self.assertIn(
         'The analytics cannot be displayed for this question as it uses randomization.',
         result_fragment.content
     )
Example #2
0
    def _update_last_visited_module_id(self, request, course, module_key, modification_date):
        """
        Saves the module id if the found modification_date is less recent than the passed modification date
        """
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=2)
        try:
            module_descriptor = modulestore().get_item(module_key)
        except ItemNotFoundError:
            return Response(errors.ERROR_INVALID_MODULE_ID, status=400)
        module = get_module_for_descriptor(
            request.user, request, module_descriptor, field_data_cache, course.id, course=course
        )

        if modification_date:
            key = KeyValueStore.Key(
                scope=Scope.user_state,
                user_id=request.user.id,
                block_scope_id=course.location,
                field_name='position'
            )
            original_store_date = field_data_cache.last_modified(key)
            if original_store_date is not None and modification_date < original_store_date:
                # old modification date so skip update
                return self._get_course_info(request, course)

        save_positions_recursively_up(request.user, request, field_data_cache, module, course=course)
        return self._get_course_info(request, course)
Example #3
0
def edxnotes(request, course_id):
    """
    Displays the EdxNotes page.
    """
    course_key = CourseKey.from_string(course_id)
    course = get_course_with_access(request.user, "load", course_key)

    if not is_feature_enabled(course):
        raise Http404

    try:
        notes = get_notes(request.user, course)
    except EdxNotesServiceUnavailable:
        raise Http404

    context = {
        "course": course,
        "search_endpoint": reverse("search_notes", kwargs={"course_id": course_id}),
        "notes": notes,
        "debug": json.dumps(settings.DEBUG),
        'position': None,
    }

    if not notes:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=2
        )
        course_module = get_module_for_descriptor(request.user, request, course, field_data_cache, course_key)
        position = get_course_position(course_module)
        if position:
            context.update({
                'position': position,
            })

    return render_to_response("edxnotes/edxnotes.html", context)
Example #4
0
    def test_entrance_exam_score(self):
        """
        test entrance exam score. we will hit the method get_entrance_exam_score to verify exam score.
        """
        exam_score = get_entrance_exam_score(self.request, self.course)
        self.assertEqual(exam_score, 0)

        # Pass the entrance exam
        # pylint: disable=maybe-no-member,no-member
        grade_dict = {'value': 1, 'max_value': 2, 'user_id': self.request.user.id}
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id,
            self.request.user,
            self.course,
            depth=2
        )
        # pylint: disable=protected-access
        module = get_module(
            self.request.user,
            self.request,
            self.problem_1.scope_ids.usage_id,
            field_data_cache,
        )._xmodule
        module.system.publish(self.problem_1, 'grade', grade_dict)

        exam_score = get_entrance_exam_score(self.request, self.course)
        # 50 percent exam score should be achieved.
        self.assertEqual(exam_score * 100, 50)
Example #5
0
def check_for_active_timelimit_module(request, course_id, course):
    """
    Looks for a timing module for the given user and course that is currently active.
    If found, returns a context dict with timer-related values to enable display of time remaining.
    """
    context = {}

    # TODO (cpennington): Once we can query the course structure, replace this with such a query
    timelimit_student_modules = StudentModule.objects.filter(student=request.user, course_id=course_id, module_type='timelimit')
    if timelimit_student_modules:
        for timelimit_student_module in timelimit_student_modules:
            # get the corresponding section_descriptor for the given StudentModel entry:
            module_state_key = timelimit_student_module.module_state_key
            timelimit_descriptor = modulestore().get_instance(course_id, Location(module_state_key))
            timelimit_module_cache = FieldDataCache.cache_for_descriptor_descendents(course.id, request.user,
                                                                                     timelimit_descriptor, depth=None)
            timelimit_module = get_module_for_descriptor(request.user, request, timelimit_descriptor,
                                                         timelimit_module_cache, course.id, position=None)
            if timelimit_module is not None and timelimit_module.category == 'timelimit' and \
                    timelimit_module.has_begun and not timelimit_module.has_ended:
                location = timelimit_module.location
                # determine where to go when the timer expires:
                if timelimit_descriptor.time_expired_redirect_url is None:
                    raise Http404("no time_expired_redirect_url specified at this location: {} ".format(timelimit_module.location))
                context['time_expired_redirect_url'] = timelimit_descriptor.time_expired_redirect_url
                # Fetch the remaining time relative to the end time as stored in the module when it was started.
                # This value should be in milliseconds.
                remaining_time = timelimit_module.get_remaining_time_in_ms()
                context['timer_expiration_duration'] = remaining_time
                context['suppress_toplevel_navigation'] = timelimit_descriptor.suppress_toplevel_navigation
                return_url = reverse('jump_to', kwargs={'course_id': course_id, 'location': location})
                context['timer_navigation_return_url'] = return_url
    return context
Example #6
0
    def _update_last_visited_sequential(self, request, course, chapter_id, sequential_id, modification_date):
        '''
        course -- xmodule
        '''
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=2)
        try:
            chapter_descriptor = get_item(course.id, 'chapter', chapter_id)
            sequential_descriptor = get_item(course.id, 'sequential', sequential_id)
        except ItemNotFoundError:
            raise error.Error(status=status.HTTP_404_NOT_FOUND)
        course_descriptor = course
        course = get_module_for_descriptor(
                request.user, request, course_descriptor, field_data_cache, course.id)
        chapter = get_module_for_descriptor(
                request.user, request, chapter_descriptor, field_data_cache, course.id)
        sequential = get_module_for_descriptor(
                request.user, request, sequential_descriptor, field_data_cache, course.id)
        if modification_date:
            key = KeyValueStore.Key(
                scope=Scope.user_state,
                user_id=request.user.id,
                block_scope_id=course.location,
                field_name=None
            )
            student_module = field_data_cache.find(key)
            if student_module:
                original_store_date = student_module.modified
                if modification_date < original_store_date:
                    # old modification date so skip update
                    return self._get_course_info(request, course)

        self.save_sequential_position(course, chapter, sequential)
        return self._get_course_info(request, course)
    def test_repeated_course_module_instantiation(self, loops, default_store, course_depth):

        with modulestore().default_store(default_store):
            course = CourseFactory.create()
            chapter = ItemFactory(parent=course, category='chapter', graded=True)
            section = ItemFactory(parent=chapter, category='sequential')
            __ = ItemFactory(parent=section, category='problem')

        fake_request = self.factory.get(
            reverse('progress', kwargs={'course_id': unicode(course.id)})
        )

        course = modulestore().get_course(course.id, depth=course_depth)

        for _ in xrange(loops):
            field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                course.id, self.user, course, depth=course_depth
            )
            course_module = get_module_for_descriptor(
                self.user,
                fake_request,
                course,
                field_data_cache,
                course.id,
                course=course
            )
            for chapter in course_module.get_children():
                for section in chapter.get_children():
                    for item in section.get_children():
                        self.assertTrue(item.graded)
    def _get_module(self, course_id, descriptor, location):
        """
        Get the module from the course from which to pattern match (or not) the 'View in Studio' buttons
        """
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course_id, self.staff_user, descriptor)

        return render.get_module(self.staff_user, self.request, location, field_data_cache)
    def test_module_render_with_jump_to_id(self):
        """
        This test validates that the /jump_to_id/<id> shorthand for intracourse linking works assertIn
        expected. Note there's a HTML element in the 'toy' course with the url_name 'toyjumpto' which
        defines this linkage
        """
        mock_request = MagicMock()
        mock_request.user = self.mock_user

        course = get_course_with_access(self.mock_user, "load", self.course_key)

        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course_key, self.mock_user, course, depth=2
        )

        module = render.get_module(
            self.mock_user, mock_request, self.course_key.make_usage_key("html", "toyjumpto"), field_data_cache
        )

        # get the rendered HTML output which should have the rewritten link
        html = module.render(STUDENT_VIEW).content

        # See if the url got rewritten to the target link
        # note if the URL mapping changes then this assertion will break
        self.assertIn("/courses/" + self.course_key.to_deprecated_string() + "/jump_to_id/vertical_test", html)
Example #10
0
def get_static_tab_contents(request, course, tab):
    """
    Returns the contents for the given static tab
    """
    loc = Location(course.location.tag, course.location.org, course.location.course, tab.type, tab.url_slug)
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id, request.user, modulestore().get_instance(course.id, loc), depth=0
    )
    tab_module = get_module(
        request.user, request, loc, field_data_cache, course.id, static_asset_path=course.static_asset_path
    )

    logging.debug("course_module = {0}".format(tab_module))

    html = ""
    if tab_module is not None:
        try:
            html = tab_module.render("student_view").content
        except Exception:  # pylint: disable=broad-except
            html = render_to_string("courseware/error-message.html", None)
            log.exception(
                u"Error rendering course={course}, tab={tab_url}".format(course=course, tab_url=tab["url_slug"])
            )

    return html
Example #11
0
def get_module_combinedopenended(request, course, location, isupload):
    location = course.location[0]+'://'+course.location[1]+'/'+course.location[2]+'/chapter/'+location
    section_descriptor = modulestore().get_instance(course.id, location, depth=None)
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course.id, request.user, section_descriptor, depth=None)
    descriptor = modulestore().get_instance_items(course.id, location,'combinedopenended',depth=None)
    content = []
    
    for x in range(len(descriptor)):
        module = get_module_for_descriptor(request.user, request, descriptor[x][1], field_data_cache, course.id,
                                         position=None, wrap_xmodule_display=True, grade_bucket_type=None,
                                         static_asset_path='')
        con = module.runtime.render(module, None, 'student_view').content
        confirm = Get_confirm()
        confirm.feed(con)
        if confirm.score_urls[0] == 'correct' and confirm.state_urls[0] == 'done':
            #content.append(add_edit_tool(con,course,descriptor[x]))
            #import logging
            #log = logging.getLogger("tracking")
            #log.debug("descriptor_location===============================\n:"+str(con)+"\n===========================")
            #c_info = Get_combinedopenended_info()
            #c_info.feed(con)
            title, body = Get_combinedopenended_info(con)
            content.append(create_discussion(request, course, descriptor[x][1].location[4], location,{'title':title,'body':body}))

    return content
def answer_entrance_exam_problem(course, request, problem, user=None):
    """
    Takes a required milestone `problem` in a `course` and fulfills it.

    Args:
        course (Course): Course object, the course the required problem is in
        request (Request): request Object
        problem (xblock): xblock object, the problem to be fulfilled
        user (User): User object in case it is different from request.user
    """
    if not user:
        user = request.user

    grade_dict = {'value': 1, 'max_value': 1, 'user_id': user.id}
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id,
        user,
        course,
        depth=2
    )
    # pylint: disable=protected-access
    module = get_module(
        user,
        request,
        problem.scope_ids.usage_id,
        field_data_cache,
    )._xmodule
    module.system.publish(problem, 'grade', grade_dict)
Example #13
0
    def test_entrance_exam_content_info(self):
        """
        test entrance exam content info method
        """
        exam_chapter, is_exam_passed = get_entrance_exam_content_info(self.request, self.course)
        self.assertEqual(exam_chapter.url_name, self.entrance_exam.url_name)
        self.assertEqual(is_exam_passed, False)

        # Pass the entrance exam
        # pylint: disable=maybe-no-member,no-member
        grade_dict = {'value': 1, 'max_value': 1, 'user_id': self.request.user.id}
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id,
            self.request.user,
            self.course,
            depth=2
        )
        # pylint: disable=protected-access
        module = get_module(
            self.request.user,
            self.request,
            self.problem_1.scope_ids.usage_id,
            field_data_cache,
        )._xmodule
        module.system.publish(self.problem_1, 'grade', grade_dict)

        exam_chapter, is_exam_passed = get_entrance_exam_content_info(self.request, self.course)
        self.assertEqual(exam_chapter, None)
        self.assertEqual(is_exam_passed, True)
Example #14
0
    def _iter_scorable_xmodules(block_structure):
        """
        Loop through all the blocks locators in the block structure, and retrieve
        the module (XModule or XBlock) associated with that locator.

        For implementation reasons, we need to pull the max_score from the
        XModule, even though the data is not user specific.  Here we bind the
        data to a SystemUser.
        """
        request = RequestFactory().get('/dummy-collect-max-grades')
        user = SystemUser()
        request.user = user
        request.session = {}
        root_block = block_structure.get_xblock(block_structure.root_block_usage_key)
        course_key = block_structure.root_block_usage_key.course_key
        cache = FieldDataCache.cache_for_descriptor_descendents(
            course_id=course_key,
            user=request.user,
            descriptor=root_block,
            descriptor_filter=lambda descriptor: descriptor.has_score,
        )
        for block_locator in block_structure.post_order_traversal():
            block = block_structure.get_xblock(block_locator)
            if getattr(block, 'has_score', False):
                module = get_module_for_descriptor(user, request, block, cache, course_key)
                yield module
Example #15
0
def get_module_by_usage_id(request, course_id, usage_id, disable_staff_debug_info=False, course=None):
    """
    Gets a module instance based on its `usage_id` in a course, for a given request/user

    Returns (instance, tracking_context)
    """
    user = request.user

    try:
        course_id = CourseKey.from_string(course_id)
        usage_key = UsageKey.from_string(unquote_slashes(usage_id)).map_into_course(course_id)
    except InvalidKeyError:
        raise Http404("Invalid location")

    try:
        descriptor = modulestore().get_item(usage_key)
        descriptor_orig_usage_key, descriptor_orig_version = modulestore().get_block_original_usage(usage_key)
    except ItemNotFoundError:
        log.warn(
            "Invalid location for course id %s: %s",
            usage_key.course_key,
            usage_key
        )
        raise Http404

    tracking_context = {
        'module': {
            'display_name': descriptor.display_name_with_default_escaped,
            'usage_key': unicode(descriptor.location),
        }
    }

    # For blocks that are inherited from a content library, we add some additional metadata:
    if descriptor_orig_usage_key is not None:
        tracking_context['module']['original_usage_key'] = unicode(descriptor_orig_usage_key)
        tracking_context['module']['original_usage_version'] = unicode(descriptor_orig_version)

    unused_masquerade, user = setup_masquerade(request, course_id, has_access(user, 'staff', descriptor, course_id))
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id,
        user,
        descriptor,
        read_only=CrawlersConfig.is_crawler(request),
    )
    instance = get_module_for_descriptor(
        user,
        request,
        descriptor,
        field_data_cache,
        usage_key.course_key,
        disable_staff_debug_info=disable_staff_debug_info,
        course=course
    )
    if instance is None:
        # Either permissions just changed, or someone is trying to be clever
        # and load something they shouldn't have access to.
        log.debug("No module %s for user %s -- access denied?", usage_key, user)
        raise Http404

    return (instance, tracking_context)
    def test_toc_toy_from_section(self):
        chapter = 'Overview'
        chapter_url = '%s/%s/%s' % ('/courses', self.course_name, chapter)
        section = 'Welcome'
        factory = RequestFactory()
        request = factory.get(chapter_url)
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.toy_course.id, self.portal_user, self.toy_course, depth=2)

        expected = ([{'active': True, 'sections':
                      [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True,
                        'format': u'Lecture Sequence', 'due': None, 'active': False},
                       {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True,
                        'format': '', 'due': None, 'active': True},
                       {'url_name': 'video_123456789012', 'display_name': 'Test Video', 'graded': True,
                        'format': '', 'due': None, 'active': False},
                       {'url_name': 'video_4f66f493ac8f', 'display_name': 'Video', 'graded': True,
                        'format': '', 'due': None, 'active': False}],
                      'url_name': 'Overview', 'display_name': u'Overview'},
                     {'active': False, 'sections':
                      [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True,
                        'format': '', 'due': None, 'active': False}],
                      'url_name': 'secret:magic', 'display_name': 'secret:magic'}])

        actual = render.toc_for_course(self.portal_user, request, self.toy_course, chapter, section, field_data_cache)
        for toc_section in expected:
            self.assertIn(toc_section, actual)
    def setUp(self):
        self.user = UserFactory.create()
        self.request = RequestFactory().get('/')
        self.request.user = self.user
        self.request.session = {}
        self.course = CourseFactory.create()

        problem_xml = OptionResponseXMLFactory().build_xml(
            question_text='The correct answer is Correct',
            num_inputs=2,
            weight=2,
            options=['Correct', 'Incorrect'],
            correct_option='Correct'
        )
        self.descriptor = ItemFactory.create(
            category='problem',
            data=problem_xml,
            display_name='Option Response Problem'
        )

        self.location = self.descriptor.location
        self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id,
            self.user,
            self.descriptor
        )
Example #18
0
def _get_module_instance_for_task(course_id, student, module_descriptor, xmodule_instance_args=None,
                                  grade_bucket_type=None):
    """
    Fetches a StudentModule instance for a given `course_id`, `student` object, and `module_descriptor`.

    `xmodule_instance_args` is used to provide information for creating a track function and an XQueue callback.
    These are passed, along with `grade_bucket_type`, to get_module_for_descriptor_internal, which sidesteps
    the need for a Request object when instantiating an xmodule instance.
    """
    # reconstitute the problem's corresponding XModule:
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course_id, student, module_descriptor)

    # get request-related tracking information from args passthrough, and supplement with task-specific
    # information:
    request_info = xmodule_instance_args.get('request_info', {}) if xmodule_instance_args is not None else {}
    task_info = {"student": student.username, "task_id": _get_task_id_from_xmodule_args(xmodule_instance_args)}

    def make_track_function():
        '''
        Make a tracking function that logs what happened.

        For insertion into ModuleSystem, and used by CapaModule, which will
        provide the event_type (as string) and event (as dict) as arguments.
        The request_info and task_info (and page) are provided here.
        '''
        return lambda event_type, event: task_track(request_info, task_info, event_type, event, page='x_module_task')

    xqueue_callback_url_prefix = xmodule_instance_args.get('xqueue_callback_url_prefix', '') \
        if xmodule_instance_args is not None else ''

    return get_module_for_descriptor_internal(student, module_descriptor, field_data_cache, course_id,
                                              make_track_function(), xqueue_callback_url_prefix,
                                              grade_bucket_type=grade_bucket_type)
Example #19
0
    def list(self, request, course, return_blocks=True, return_nav=True, *args, **kwargs):
        """
        REST API endpoint for listing all the blocks and/or navigation information in the course,
        while regarding user access and roles.

        Arguments:
            request - Django request object
            course - course module object
            return_blocks - If true, returns the blocks information for the course.
            return_nav - If true, returns the navigation information for the course.
        """
        # set starting point
        start_block = course

        # initialize request and result objects
        request_info = self.RequestInfo(request, course)
        result_data = self.ResultData(return_blocks, return_nav)

        # create and populate a field data cache by pre-fetching for the course (with depth=None)
        request_info.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=None,
        )

        # start the recursion with the start_block
        self.recurse_blocks_nav(request_info, result_data, self.BlockInfo(start_block, request_info))

        # return response
        response = {"root": unicode(start_block.location)}
        result_data.update_response(response, return_blocks, return_nav)
        return Response(response)
    def test_module_render_with_jump_to_id(self):
        """
        This test validates that the /jump_to_id/<id> shorthand for intracourse linking works assertIn
        expected. Note there's a HTML element in the 'toy' course with the url_name 'toyjumpto' which
        defines this linkage
        """
        mock_request = MagicMock()
        mock_request.user = self.mock_user

        course = get_course_with_access(self.mock_user, self.course_id, 'load')

        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course_id, self.mock_user, course, depth=2)

        module = render.get_module(
            self.mock_user,
            mock_request,
            Location('i4x', 'edX', 'toy', 'html', 'toyjumpto'),
            field_data_cache,
            self.course_id
        )

        # get the rendered HTML output which should have the rewritten link
        html = module.render('student_view').content

        # See if the url got rewritten to the target link
        # note if the URL mapping changes then this assertion will break
        self.assertIn('/courses/' + self.course_id + '/jump_to_id/vertical_test', html)
Example #21
0
def answer_problem(course, request, problem, score=1, max_value=1):
    """
    Records an answer for the given problem.

    Arguments:
        course (Course): Course object, the course the required problem is in
        request (Request): request Object
        problem (xblock): xblock object, the problem to be answered
        score (float): The new score for the problem
        max_value (float): The new maximum score for the problem
    """

    user = request.user
    grade_dict = {'value': score, 'max_value': max_value, 'user_id': user.id}
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id,
        user,
        course,
        depth=2
    )
    module = get_module(
        user,
        request,
        problem.location,
        field_data_cache,
    )
    module.runtime.publish(problem, 'grade', grade_dict)
def student_course_progress(request, course_id, username):
    from django.contrib.auth.models import User
    from courseware.model_data import FieldDataCache
    from courseware import grades
    from django.http import Http404, HttpResponse, HttpResponseRedirect

    student=User.objects.filter(username=username)
    
    if not student.exists():
        return HttpResponse("Student '%s' not exists." % username)

    student=student[0]

    #return HttpResponse(request.session)

    try:
        course=get_course_by_id(course_id)
    except:
        return HttpResponse("Course '%s' not exists." % course_id)

    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course_id, student, course, depth=None)
    grade_summary = grades.grade(student, request, course, field_data_cache)
    progress="{totalscore:.0%}".format(totalscore=grade_summary['percent'])

    return HttpResponse("course:%s<br>user:%s<br>progress:%s" % (course_id,username,progress))
Example #23
0
def prep_course_for_grading(course, request):
    """Set up course module for overrides to function properly"""
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course.id, request.user, course, depth=2)
    course = get_module_for_descriptor(request.user, request, course, field_data_cache, course.id, course=course)

    course._field_data_cache = {}  # pylint: disable=protected-access
    course.set_grading_policy(course.grading_policy)
Example #24
0
    def test_entrance_exam_passed_message_and_course_content(self):
        """
        Unit Test: exam passing message and rest of the course section should be present
        when user achieves the entrance exam milestone/pass the exam.
        """
        url = reverse(
            'courseware_section',
            kwargs={
                'course_id': unicode(self.course.id),
                'chapter': self.entrance_exam.location.name,
                'section': self.exam_1.location.name
            }
        )

        # pylint: disable=maybe-no-member,no-member
        grade_dict = {'value': 1, 'max_value': 1, 'user_id': self.request.user.id}
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id,
            self.request.user,
            self.course,
            depth=2
        )
        # pylint: disable=protected-access
        module = get_module(
            self.request.user,
            self.request,
            self.problem_1.scope_ids.usage_id,
            field_data_cache,
        )._xmodule
        module.system.publish(self.problem_1, 'grade', grade_dict)

        resp = self.client.get(url)
        self.assertNotIn('To access course materials, you must score', resp.content)
        self.assertIn('You have passed the entrance exam.', resp.content)
        self.assertIn('Lesson 1', resp.content)
Example #25
0
def answer_problem(course, request, problem, score=1, max_value=1):
    """
    Records a correct answer for the given problem.

    Arguments:
        course (Course): Course object, the course the required problem is in
        request (Request): request Object
        problem (xblock): xblock object, the problem to be answered
    """

    user = request.user
    grade_dict = {'value': score, 'max_value': max_value, 'user_id': user.id}
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id,
        user,
        course,
        depth=2
    )
    # pylint: disable=protected-access
    module = get_module(
        user,
        request,
        problem.scope_ids.usage_id,
        field_data_cache,
    )._xmodule
    module.system.publish(problem, 'grade', grade_dict)
Example #26
0
def get_static_tab_contents(request, course, tab):
    """
    Returns the contents for the given static tab
    """
    loc = course.id.make_usage_key(
        tab.type,
        tab.url_slug,
    )
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id, request.user, modulestore().get_item(loc), depth=0
    )
    tab_module = get_module(
        request.user, request, loc, field_data_cache, static_asset_path=course.static_asset_path
    )

    logging.debug('course_module = {0}'.format(tab_module))

    html = ''
    if tab_module is not None:
        try:
            html = tab_module.render(STUDENT_VIEW).content
        except Exception:  # pylint: disable=broad-except
            html = render_to_string('courseware/error-message.html', None)
            log.exception(
                u"Error rendering course={course}, tab={tab_url}".format(course=course, tab_url=tab['url_slug'])
            )

    return html
Example #27
0
    def rebind_noauth_module_to_user(module, real_user):
        """
        A function that allows a module to get re-bound to a real user if it was previously bound to an AnonymousUser.

        Will only work within a module bound to an AnonymousUser, e.g. one that's instantiated by the noauth_handler.

        Arguments:
            module (any xblock type):  the module to rebind
            real_user (django.contrib.auth.models.User):  the user to bind to

        Returns:
            nothing (but the side effect is that module is re-bound to real_user)
        """
        if user.is_authenticated():
            err_msg = ("rebind_noauth_module_to_user can only be called from a module bound to "
                       "an anonymous user")
            log.error(err_msg)
            raise LmsModuleRenderError(err_msg)

        field_data_cache_real_user = FieldDataCache.cache_for_descriptor_descendents(
            course_id,
            real_user,
            module.descriptor,
            asides=XBlockAsidesConfig.possible_asides(),
        )
        student_data_real_user = KvsFieldData(DjangoKeyValueStore(field_data_cache_real_user))

        (inner_system, inner_student_data) = get_module_system_for_user(
            user=real_user,
            student_data=student_data_real_user,  # These have implicit user bindings, rest of args considered not to
            descriptor=module.descriptor,
            course_id=course_id,
            track_function=track_function,
            xqueue_callback_url_prefix=xqueue_callback_url_prefix,
            position=position,
            wrap_xmodule_display=wrap_xmodule_display,
            grade_bucket_type=grade_bucket_type,
            static_asset_path=static_asset_path,
            user_location=user_location,
            request_token=request_token,
            course=course
        )

        module.descriptor.bind_for_student(
            inner_system,
            real_user.id,
            [
                partial(OverrideFieldData.wrap, real_user, course),
                partial(LmsFieldData, student_data=inner_student_data),
            ],
        )

        module.descriptor.scope_ids = (
            module.descriptor.scope_ids._replace(user_id=real_user.id)
        )
        module.scope_ids = module.descriptor.scope_ids  # this is needed b/c NamedTuples are immutable
        # now bind the module to the new ModuleSystem instance and vice-versa
        module.runtime = inner_system
        inner_system.xmodule_instance = module
Example #28
0
def get_module_by_usage_id(request, course_id, usage_id, disable_staff_debug_info=False, course=None):
    """
    Gets a module instance based on its `usage_id` in a course, for a given request/user

    Returns (instance, tracking_context)
    """
    user = request.user

    try:
        course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
        usage_key = course_id.make_usage_key_from_deprecated_string(unquote_slashes(usage_id))
    except InvalidKeyError:
        raise Http404("Invalid location")

    try:
        descriptor = modulestore().get_item(usage_key)
        descriptor_orig_usage_key, descriptor_orig_version = modulestore().get_block_original_usage(usage_key)
    except ItemNotFoundError:
        log.warn(
            "Invalid location for course id %s: %s",
            usage_key.course_key,
            usage_key
        )
        raise Http404

    tracking_context = {
        'module': {
            'display_name': descriptor.display_name_with_default_escaped,
            'usage_key': unicode(descriptor.location),
        }
    }

    # For blocks that are inherited from a content library, we add some additional metadata:
    if descriptor_orig_usage_key is not None:
        tracking_context['module']['original_usage_key'] = unicode(descriptor_orig_usage_key)
        tracking_context['module']['original_usage_version'] = unicode(descriptor_orig_version)

    unused_masquerade, user = setup_masquerade(request, course_id, has_access(user, 'staff', descriptor, course_id))
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id,
        user,
        descriptor
    )
    instance = get_module_for_descriptor(
        user,
        request,
        descriptor,
        field_data_cache,
        usage_key.course_key,
        disable_staff_debug_info=disable_staff_debug_info,
        course=course
    )
    if instance is None:
        # Either permissions just changed, or someone is trying to be clever
        # and load something they shouldn't have access to.
        log.debug("No module %s for user %s -- access denied?", usage_key, user)
        raise Http404

    return (instance, tracking_context)
def get_discussion_context(request, course, location, parent_location,portfolio_user):
        section_descriptor = modulestore().get_instance(course.id, parent_location, depth=None)
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course.id, portfolio_user, section_descriptor, depth=None)
        descriptor = modulestore().get_item(location)
        module = get_module_for_descriptor(portfolio_user, request, descriptor, field_data_cache, course.id,
                                     position=None, wrap_xmodule_display=True, grade_bucket_type=None,
                                     static_asset_path='')
        return module.runtime.render(module, None, 'student_view').content
Example #30
0
def get_course_lti_endpoints(request, course_id):
    """
    View that, given a course_id, returns the a JSON object that enumerates all of the LTI endpoints for that course.

    The LTI 2.0 result service spec at
    http://www.imsglobal.org/lti/ltiv2p0/uml/purl.imsglobal.org/vocab/lis/v2/outcomes/Result/service.html
    says "This specification document does not prescribe a method for discovering the endpoint URLs."  This view
    function implements one way of discovering these endpoints, returning a JSON array when accessed.

    Arguments:
        request (django request object):  the HTTP request object that triggered this view function
        course_id (unicode):  id associated with the course

    Returns:
        (django response object):  HTTP response.  404 if course is not found, otherwise 200 with JSON body.
    """
    try:
        course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    except InvalidKeyError:
        return HttpResponse(status=404)

    try:
        course = get_course(course_key, depth=2)
    except ValueError:
        return HttpResponse(status=404)

    anonymous_user = AnonymousUser()
    anonymous_user.known = False  # make these "noauth" requests like module_render.handle_xblock_callback_noauth
    lti_descriptors = modulestore().get_items(course.id, category='lti')

    lti_noauth_modules = [
        get_module_for_descriptor(
            anonymous_user,
            request,
            descriptor,
            FieldDataCache.cache_for_descriptor_descendents(
                course_key,
                anonymous_user,
                descriptor
            ),
            course_key
        )
        for descriptor in lti_descriptors
    ]

    endpoints = [
        {
            'display_name': module.display_name,
            'lti_2_0_result_service_json_endpoint': module.get_outcome_service_url(
                service_name='lti_2_0_result_rest_handler') + "/user/{anon_user_id}",
            'lti_1_1_result_service_xml_endpoint': module.get_outcome_service_url(
                service_name='grade_handler'),
        }
        for module in lti_noauth_modules
    ]

    return HttpResponse(json.dumps(endpoints), content_type='application/json')
Example #31
0
def get_course_lti_endpoints(request, course_id):
    """
    View that, given a course_id, returns the a JSON object that enumerates all of the LTI endpoints for that course.

    The LTI 2.0 result service spec at
    http://www.imsglobal.org/lti/ltiv2p0/uml/purl.imsglobal.org/vocab/lis/v2/outcomes/Result/service.html
    says "This specification document does not prescribe a method for discovering the endpoint URLs."  This view
    function implements one way of discovering these endpoints, returning a JSON array when accessed.

    Arguments:
        request (django request object):  the HTTP request object that triggered this view function
        course_id (unicode):  id associated with the course

    Returns:
        (django response object):  HTTP response.  404 if course is not found, otherwise 200 with JSON body.
    """
    try:
        course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    except InvalidKeyError:
        return HttpResponse(status=404)

    try:
        course = get_course(course_key, depth=2)
    except ValueError:
        return HttpResponse(status=404)

    anonymous_user = AnonymousUser()
    anonymous_user.known = False  # make these "noauth" requests like module_render.handle_xblock_callback_noauth
    lti_descriptors = modulestore().get_items(course.id, qualifiers={'category': 'lti'})

    lti_noauth_modules = [
        get_module_for_descriptor(
            anonymous_user,
            request,
            descriptor,
            FieldDataCache.cache_for_descriptor_descendents(
                course_key,
                anonymous_user,
                descriptor
            ),
            course_key
        )
        for descriptor in lti_descriptors
    ]

    endpoints = [
        {
            'display_name': module.display_name,
            'lti_2_0_result_service_json_endpoint': module.get_outcome_service_url(
                service_name='lti_2_0_result_rest_handler') + "/user/{anon_user_id}",
            'lti_1_1_result_service_xml_endpoint': module.get_outcome_service_url(
                service_name='grade_handler'),
        }
        for module in lti_noauth_modules
    ]

    return HttpResponse(json.dumps(endpoints), content_type='application/json')
    def get_module_for_user(self, user):
        """Helper function to get useful module at self.location in self.course_id for user"""
        mock_request = MagicMock()
        mock_request.user = user
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(self.course.id, user, self.course, depth=2)

        return render.get_module(  # pylint: disable=protected-access
            user, mock_request, self.lti.location, field_data_cache
        )._xmodule
Example #33
0
 def create_module(descriptor):
     """
     Factory method for creating and binding a module for the given descriptor.
     """
     field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
         self.course_id, self.request.user, descriptor, depth=0,
     )
     return get_module_for_descriptor(
         self.request.user, self.request, descriptor, field_data_cache, self.course_id
     )
    def get_module_for_user(self, user):
        """Helper function to get useful module at self.location in self.course_id for user"""
        mock_request = MagicMock()
        mock_request.user = user
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id, user, self.course, depth=2)

        return render.get_module(  # pylint: disable=protected-access
            user, mock_request, self.problem.location, field_data_cache,
            self.course.id)._xmodule
Example #35
0
def prep_course_for_grading(course, request):
    """Set up course module for overrides to function properly"""
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id, request.user, course, depth=2)
    course = get_module_for_descriptor(
        request.user, request, course, field_data_cache, course.id, course=course
    )

    course._field_data_cache = {}  # pylint: disable=protected-access
    course.set_grading_policy(course.grading_policy)
 def setUp(self):
     super(TestInlineAnalytics, self).setUp()
     self.user = UserFactory.create()
     self.request = RequestFactory().get('/')
     self.request.user = self.user
     self.request.session = {}
     self.course = CourseFactory.create(
         org='A',
         number='B',
         display_name='C',
     )
     self.staff = StaffFactory(course_key=self.course.id)
     self.instructor = InstructorFactory(course_key=self.course.id)
     self.problem_xml = OptionResponseXMLFactory().build_xml(
         question_text='The correct answer is Correct',
         num_inputs=2,
         weight=2,
         options=['Correct', 'Incorrect'],
         correct_option='Correct',
     )
     self.descriptor = ItemFactory.create(
         category='problem',
         data=self.problem_xml,
         display_name='Option Response Problem',
         rerandomize='never',
     )
     self.location = self.descriptor.location
     self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
         self.course.id,
         self.user,
         self.descriptor,
     )
     self.field_data_cache_staff = FieldDataCache.cache_for_descriptor_descendents(
         self.course.id,
         self.staff,
         self.descriptor,
     )
     self.field_data_cache_instructor = FieldDataCache.cache_for_descriptor_descendents(
         self.course.id,
         self.instructor,
         self.descriptor,
     )
Example #37
0
def ccx_grades_csv(request, course):
    """
    Download grades as CSV.
    """
    # Need course module for overrides to function properly
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id, request.user, course, depth=2)
    course = get_module_for_descriptor(request.user, request, course,
                                       field_data_cache, course.id)
    ccx = get_ccx_for_coach(course, request.user)
    with ccx_context(ccx):
        # The grading policy for the MOOC is probably already cached.  We need
        # to make sure we have the CCX grading policy loaded.
        course._field_data_cache = {}  # pylint: disable=protected-access
        course.set_grading_policy(course.grading_policy)

        enrolled_students = User.objects.filter(
            ccxmembership__ccx=ccx, ccxmembership__active=1).order_by(
                'username').select_related("profile")
        grades = iterate_grades_for(course, enrolled_students)

        header = None
        rows = []
        for student, gradeset, __ in grades:
            if gradeset:
                # We were able to successfully grade this student for this
                # course.
                if not header:
                    # Encode the header row in utf-8 encoding in case there are
                    # unicode characters
                    header = [
                        section['label'].encode('utf-8')
                        for section in gradeset[u'section_breakdown']
                    ]
                    rows.append(["id", "email", "username", "grade"] + header)

                percents = {
                    section['label']: section.get('percent', 0.0)
                    for section in gradeset[u'section_breakdown']
                    if 'label' in section
                }

                row_percents = [percents.get(label, 0.0) for label in header]
                rows.append([
                    student.id, student.email, student.username,
                    gradeset['percent']
                ] + row_percents)

        buf = StringIO()
        writer = csv.writer(buf)
        for row in rows:
            writer.writerow(row)

        return HttpResponse(buf.getvalue(), content_type='text/plain')
Example #38
0
def _get_module_instance_for_task(course_id,
                                  student,
                                  module_descriptor,
                                  xmodule_instance_args=None,
                                  grade_bucket_type=None,
                                  course=None):
    """
    Fetches a StudentModule instance for a given `course_id`, `student` object, and `module_descriptor`.

    `xmodule_instance_args` is used to provide information for creating a track function and an XQueue callback.
    These are passed, along with `grade_bucket_type`, to get_module_for_descriptor_internal, which sidesteps
    the need for a Request object when instantiating an xmodule instance.
    """
    # reconstitute the problem's corresponding XModule:
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id, student, module_descriptor)
    student_data = KvsFieldData(DjangoKeyValueStore(field_data_cache))

    # get request-related tracking information from args passthrough, and supplement with task-specific
    # information:
    request_info = xmodule_instance_args.get(
        'request_info', {}) if xmodule_instance_args is not None else {}
    task_info = {
        "student": student.username,
        "task_id": _get_task_id_from_xmodule_args(xmodule_instance_args)
    }

    def make_track_function():
        '''
        Make a tracking function that logs what happened.

        For insertion into ModuleSystem, and used by CapaModule, which will
        provide the event_type (as string) and event (as dict) as arguments.
        The request_info and task_info (and page) are provided here.
        '''
        return lambda event_type, event: task_track(
            request_info, task_info, event_type, event, page='x_module_task')

    xqueue_callback_url_prefix = xmodule_instance_args.get('xqueue_callback_url_prefix', '') \
        if xmodule_instance_args is not None else ''

    return get_module_for_descriptor_internal(
        user=student,
        descriptor=module_descriptor,
        student_data=student_data,
        course_id=course_id,
        track_function=make_track_function(),
        xqueue_callback_url_prefix=xqueue_callback_url_prefix,
        grade_bucket_type=grade_bucket_type,
        # This module isn't being used for front-end rendering
        request_token=None,
        # pass in a loaded course for override enabling
        course=course)
 def setup_modulestore(self, default_ms, num_finds, num_sends):
     self.course_key = self.create_toy_course()
     self.chapter = 'Overview'
     chapter_url = '%s/%s/%s' % ('/courses', self.course_key, self.chapter)
     factory = RequestFactory()
     self.request = factory.get(chapter_url)
     self.request.user = UserFactory()
     self.modulestore = self.store._get_modulestore_for_courseid(self.course_key)
     with check_mongo_calls(self.modulestore, num_finds, num_sends):
         self.toy_course = self.store.get_course(self.toy_loc, depth=2)
         self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
             self.toy_loc, self.request.user, self.toy_course, depth=2)
    def _return_table_of_contents(self):
        """
        Returns table of content for the entrance exam specific to this test

        Returns the table of contents for course self.course, for chapter
        self.entrance_exam, and for section self.exam1
        """
        self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(  # pylint: disable=attribute-defined-outside-init
            self.course.id, self.request.user, self.entrance_exam)
        return toc_for_course(self.request.user, self.request, self.course,
                              self.entrance_exam.url_name,
                              self.exam_1.url_name, self.field_data_cache)
Example #41
0
    def _get_module(self, course_id, descriptor, location):
        """
        Get the module from the course from which to pattern match (or not) the 'View in Studio' buttons
        """
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course_id, self.staff_user, descriptor)

        return render.get_module(
            self.staff_user,
            self.request,
            location,
            field_data_cache,
        )
def _get_course_module(course_descriptor, user):
    # Fake a request to fool parts of the courseware that want to inspect it.
    request = get_request_or_stub()
    request.user = user

    # Now evil modulestore magic to inflate our descriptor with user state and
    # permissions checks.
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_descriptor.id, user, course_descriptor, depth=1, read_only=True,
    )
    return get_module_for_descriptor(
        user, request, course_descriptor, field_data_cache, course_descriptor.id, course=course_descriptor,
    )
Example #43
0
def ccx_gradebook(request, course):
    """
    Show the gradebook for this CCX.
    """
    # Need course module for overrides to function properly
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id, request.user, course, depth=2)
    course = get_module_for_descriptor(request.user, request, course,
                                       field_data_cache, course.id)

    ccx = get_ccx_for_coach(course, request.user)
    with ccx_context(ccx):
        # The grading policy for the MOOC is probably already cached.  We need
        # to make sure we have the CCX grading policy loaded.
        course._field_data_cache = {}  # pylint: disable=protected-access
        course.set_grading_policy(course.grading_policy)

        enrolled_students = User.objects.filter(
            ccxmembership__ccx=ccx, ccxmembership__active=1).order_by(
                'username').select_related("profile")

        student_info = [{
            'username':
            student.username,
            'id':
            student.id,
            'email':
            student.email,
            'grade_summary':
            student_grades(student, request, course),
            'realname':
            student.profile.name,
        } for student in enrolled_students]

        return render_to_response(
            'courseware/gradebook.html', {
                'students':
                student_info,
                'course':
                course,
                'course_id':
                course.id,
                'staff_access':
                request.user.is_staff,
                'ordered_grades':
                sorted(course.grade_cutoffs.items(),
                       key=lambda i: i[1],
                       reverse=True),
            })
Example #44
0
def progress(request, course_id, student_id=None):
    """ User progress. We show the grade bar and every problem score.

    Course staff are allowed to see the progress of students in their class.
    """
    course = get_course_with_access(request.user,
                                    course_id,
                                    'load',
                                    depth=None)
    staff_access = has_access(request.user, course, 'staff')

    if student_id is None or student_id == request.user.id:
        # always allowed to see your own profile
        student = request.user
    else:
        # Requesting access to a different student's profile
        if not staff_access:
            raise Http404
        student = User.objects.get(id=int(student_id))

    # NOTE: To make sure impersonation by instructor works, use
    # student instead of request.user in the rest of the function.

    # The pre-fetching of groups is done to make auth checks not require an
    # additional DB lookup (this kills the Progress page in particular).
    student = User.objects.prefetch_related("groups").get(id=student.id)

    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id, student, course, depth=None)

    courseware_summary = grades.progress_summary(student, request, course,
                                                 field_data_cache)
    grade_summary = grades.grade(student, request, course, field_data_cache)

    if courseware_summary is None:
        #This means the student didn't have access to the course (which the instructor requested)
        raise Http404

    context = {
        'course': course,
        'courseware_summary': courseware_summary,
        'grade_summary': grade_summary,
        'staff_access': staff_access,
        'student': student,
    }
    context.update()

    return render_to_response('courseware/progress.html', context)
Example #45
0
def check_for_active_timelimit_module(request, course_id, course):
    """
    Looks for a timing module for the given user and course that is currently active.
    If found, returns a context dict with timer-related values to enable display of time remaining.
    """
    context = {}

    # TODO (cpennington): Once we can query the course structure, replace this with such a query
    timelimit_student_modules = StudentModule.objects.filter(
        student=request.user, course_id=course_id, module_type='timelimit')
    if timelimit_student_modules:
        for timelimit_student_module in timelimit_student_modules:
            # get the corresponding section_descriptor for the given StudentModel entry:
            module_state_key = timelimit_student_module.module_state_key
            timelimit_descriptor = modulestore().get_instance(
                course_id, Location(module_state_key))
            timelimit_module_cache = FieldDataCache.cache_for_descriptor_descendents(
                course.id, request.user, timelimit_descriptor, depth=None)
            timelimit_module = get_module_for_descriptor(
                request.user,
                request,
                timelimit_descriptor,
                timelimit_module_cache,
                course.id,
                position=None)
            if timelimit_module is not None and timelimit_module.category == 'timelimit' and \
                    timelimit_module.has_begun and not timelimit_module.has_ended:
                location = timelimit_module.location
                # determine where to go when the timer expires:
                if timelimit_descriptor.time_expired_redirect_url is None:
                    raise Http404(
                        "no time_expired_redirect_url specified at this location: {} "
                        .format(timelimit_module.location))
                context[
                    'time_expired_redirect_url'] = timelimit_descriptor.time_expired_redirect_url
                # Fetch the remaining time relative to the end time as stored in the module when it was started.
                # This value should be in milliseconds.
                remaining_time = timelimit_module.get_remaining_time_in_ms()
                context['timer_expiration_duration'] = remaining_time
                context[
                    'suppress_toplevel_navigation'] = timelimit_descriptor.suppress_toplevel_navigation
                return_url = reverse('jump_to',
                                     kwargs={
                                         'course_id': course_id,
                                         'location': location
                                     })
                context['timer_navigation_return_url'] = return_url
    return context
Example #46
0
def field_data_cache_for_grading(course, user):
    """
    Given a CourseDescriptor and User, create the FieldDataCache for grading.

    This will generate a FieldDataCache that only loads state for those things
    that might possibly affect the grading process, and will ignore things like
    Videos.
    """
    descriptor_filter = partial(descriptor_affects_grading,
                                course.block_types_affecting_grading)
    return FieldDataCache.cache_for_descriptor_descendents(
        course.id,
        user,
        course,
        depth=None,
        descriptor_filter=descriptor_filter)
Example #47
0
    def rebind_noauth_module_to_user(module, real_user):
        """
        A function that allows a module to get re-bound to a real user if it was previously bound to an AnonymousUser.

        Will only work within a module bound to an AnonymousUser, e.g. one that's instantiated by the noauth_handler.

        Arguments:
            module (any xblock type):  the module to rebind
            real_user (django.contrib.auth.models.User):  the user to bind to

        Returns:
            nothing (but the side effect is that module is re-bound to real_user)
        """
        if user.is_authenticated():
            err_msg = (
                "rebind_noauth_module_to_user can only be called from a module bound to "
                "an anonymous user")
            log.error(err_msg)
            raise LmsModuleRenderError(err_msg)

        field_data_cache_real_user = FieldDataCache.cache_for_descriptor_descendents(
            course_id, real_user, module.descriptor)

        (inner_system, inner_student_data) = get_module_system_for_user(
            real_user,
            field_data_cache_real_user,  # These have implicit user bindings, rest of args considered not to
            module.descriptor,
            course_id,
            track_function,
            xqueue_callback_url_prefix,
            position,
            wrap_xmodule_display,
            grade_bucket_type,
            static_asset_path,
            user_location)
        # rebinds module to a different student.  We'll change system, student_data, and scope_ids
        module.descriptor.bind_for_student(
            inner_system,
            LmsFieldData(module.descriptor._field_data, inner_student_data)  # pylint: disable=protected-access
        )
        module.descriptor.scope_ids = (
            module.descriptor.scope_ids._replace(user_id=real_user.id)  # pylint: disable=protected-access
        )
        module.scope_ids = module.descriptor.scope_ids  # this is needed b/c NamedTuples are immutable
        # now bind the module to the new ModuleSystem instance and vice-versa
        module.runtime = inner_system
        inner_system.xmodule_instance = module
Example #48
0
def edxnotes(request, course_id):
    """
    Displays the EdxNotes page.

    Arguments:
        request: HTTP request object
        course_id: course id

    Returns:
        Rendered HTTP response.
    """
    course_key = CourseKey.from_string(course_id)
    course = get_course_with_access(request.user, "load", course_key)

    if not is_feature_enabled(course, request.user):
        raise Http404

    notes_info = get_notes(request, course)
    has_notes = (len(notes_info.get('results')) > 0)
    context = {
        "course": course,
        "notes_endpoint": reverse("notes", kwargs={"course_id": course_id}),
        "notes": notes_info,
        "page_size": DEFAULT_PAGE_SIZE,
        "debug": settings.DEBUG,
        'position': None,
        'disabled_tabs': settings.NOTES_DISABLED_TABS,
        'has_notes': has_notes,
    }

    if not has_notes:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=2)
        course_module = get_module_for_descriptor(request.user,
                                                  request,
                                                  course,
                                                  field_data_cache,
                                                  course_key,
                                                  course=course)
        position = get_course_position(course_module)
        if position:
            context.update({
                'position': position,
            })

    return render_to_response("edxnotes/edxnotes.html", context)
 def setUp(self):
     self.user = UserFactory.create()
     self.request = RequestFactory().get('/')
     self.request.user = self.user
     self.request.session = {}
     self.course = CourseFactory.create()
     self.content_string = '<p>This is the content<p>'
     self.rewrite_link = '<a href="/static/foo/content">Test rewrite</a>'
     self.rewrite_bad_link = '<img src="/static//file.jpg" />'
     self.course_link = '<a href="/course/bar/content">Test course rewrite</a>'
     self.descriptor = ItemFactory.create(
         category='html',
         data=self.content_string + self.rewrite_link +
         self.rewrite_bad_link + self.course_link)
     self.location = self.descriptor.location
     self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
         self.course.id, self.user, self.descriptor)
Example #50
0
def find_target_student_module(request, user_id, course_id, mod_id):
    """
    Retrieve target StudentModule
    """
    user = User.objects.get(id=user_id)
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id,
        user,
        modulestore().get_instance(course_id, mod_id),
        depth=0,
        select_for_update=True
    )
    instance = get_module(user, request, mod_id, field_data_cache, course_id, grade_bucket_type='xqueue')
    if instance is None:
        msg = "No module {0} for user {1}--access denied?".format(mod_id, user)
        log.debug(msg)
        raise Http404
    return instance
Example #51
0
    def test_histogram_enabled_for_unscored_xmodules(self):
        """Histograms should not display for xmodules which are not scored."""

        html_descriptor = ItemFactory.create(
            category='html', data='Here are some course details.')
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id, self.user, self.descriptor)
        with patch(
                'xmodule_modifiers.grade_histogram') as mock_grade_histogram:
            mock_grade_histogram.return_value = []
            module = render.get_module(
                self.user,
                self.request,
                html_descriptor.location,
                field_data_cache,
            )
            module.render(STUDENT_VIEW)
            self.assertFalse(mock_grade_histogram.called)
    def test_entrance_exam_passed_message_and_course_content(self):
        """
        Unit Test: exam passing message and rest of the course section should be present
        when user achieves the entrance exam milestone/pass the exam.
        """
        url = reverse('courseware_section',
                      kwargs={
                          'course_id': unicode(self.course.id),
                          'chapter': self.entrance_exam.location.name,
                          'section': self.exam_1.location.name
                      })

        # pylint: disable=maybe-no-member,no-member
        grade_dict = {
            'value': 1,
            'max_value': 1,
            'user_id': self.request.user.id
        }
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id, self.request.user, self.course, depth=2)
        # pylint: disable=protected-access
        module = get_module(
            self.request.user,
            self.request,
            self.problem_1.scope_ids.usage_id,
            field_data_cache,
        )._xmodule
        module.system.publish(self.problem_1, 'grade', grade_dict)

        # pylint: disable=protected-access
        module = get_module(
            self.request.user,
            self.request,
            self.problem_2.scope_ids.usage_id,
            field_data_cache,
        )._xmodule
        module.system.publish(self.problem_2, 'grade', grade_dict)

        resp = self.client.get(url)
        if settings.FEATURES.get('ENTRANCE_EXAMS', False):
            self.assertNotIn('To access course materials, you must score',
                             resp.content)
            self.assertIn('You have passed the entrance exam.', resp.content)
            self.assertIn('Lesson 1', resp.content)
 def test_no_problems(self):
     descriptor = ItemFactory.create(
         category='html',
         display_name='HTML Component',
     )
     location = descriptor.location
     field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
         self.course.id,
         self.user,
         descriptor
     )
     module = render.get_module(
         self.user,
         self.request,
         location,
         field_data_cache,
     )
     result_fragment = module.render(STUDENT_VIEW)
     self.assertNotIn('Staff Analytics Info', result_fragment.content)
    def test_get_entrance_exam_content(self):
        """
        test get entrance exam content method
        """
        exam_chapter = get_entrance_exam_content(self.request, self.course)
        if settings.FEATURES.get('ENTRANCE_EXAMS', False):
            self.assertEqual(exam_chapter.url_name,
                             self.entrance_exam.url_name)
            self.assertFalse(
                user_has_passed_entrance_exam(self.request, self.course))

            # Pass the entrance exam
            # pylint: disable=maybe-no-member,no-member
            grade_dict = {
                'value': 1,
                'max_value': 1,
                'user_id': self.request.user.id
            }
            field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                self.course.id, self.request.user, self.course, depth=2)
            # pylint: disable=protected-access
            module = get_module(
                self.request.user,
                self.request,
                self.problem_1.scope_ids.usage_id,
                field_data_cache,
            )._xmodule
            module.system.publish(self.problem_1, 'grade', grade_dict)

            # pylint: disable=protected-access
            module = get_module(
                self.request.user,
                self.request,
                self.problem_2.scope_ids.usage_id,
                field_data_cache,
            )._xmodule
            module.system.publish(self.problem_2, 'grade', grade_dict)

            exam_chapter = get_entrance_exam_content(self.request, self.course)
            self.assertEqual(exam_chapter, None)
            self.assertTrue(
                user_has_passed_entrance_exam(self.request, self.course))
Example #55
0
def find_target_student_module(request, user_id, course_id, mod_id):
    """
    Retrieve target StudentModule
    """
    course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    usage_key = course_id.make_usage_key_from_deprecated_string(mod_id)
    user = User.objects.get(id=user_id)
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id,
        user,
        modulestore().get_item(usage_key),
        depth=0,
        select_for_update=True
    )
    instance = get_module(user, request, usage_key, field_data_cache, grade_bucket_type='xqueue')
    if instance is None:
        msg = "No module {0} for user {1}--access denied?".format(mod_id, user)
        log.debug(msg)
        raise Http404
    return instance
Example #56
0
def load_single_xblock(request, user_id, course_id, usage_key_string, course=None):
    """
    Load a single XBlock identified by usage_key_string.
    """
    usage_key = UsageKey.from_string(usage_key_string)
    course_key = CourseKey.from_string(course_id)
    usage_key = usage_key.map_into_course(course_key)
    user = User.objects.get(id=user_id)
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_key,
        user,
        modulestore().get_item(usage_key),
        depth=0,
    )
    instance = get_module(user, request, usage_key, field_data_cache, grade_bucket_type='xqueue', course=course)
    if instance is None:
        msg = "No module {0} for user {1}--access denied?".format(usage_key_string, user)
        log.debug(msg)
        raise Http404
    return instance
Example #57
0
    def _prefetch_and_bind_course(self):
        """
        Prefetches all descendant data for the requested section and
        sets up the runtime, which binds the request user to the section.
        """
        self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course_key,
            self.effective_user,
            self.course,
            depth=CONTENT_DEPTH,
        )

        self.course = get_module_for_descriptor(
            self.effective_user,
            self.request,
            self.course,
            self.field_data_cache,
            self.course_key,
            course=self.course,
        )
Example #58
0
    def _last_visited_module_path(self, request, course):
        """
        Returns the path from the last module visited by the current user in the given course up to
        the course module. If there is no such visit, the first item deep enough down the course
        tree is used.
        """
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=2)

        course_module = get_module_for_descriptor(request.user, request, course, field_data_cache, course.id)

        path = [course_module]
        chapter = get_current_child(course_module, min_depth=2)
        if chapter is not None:
            path.append(chapter)
            section = get_current_child(chapter, min_depth=1)
            if section is not None:
                path.append(section)

        path.reverse()
        return path
    def setUp(self):
        self.user = UserFactory.create()
        self.request = RequestFactory().get('/')
        self.request.user = self.user
        self.request.session = {}
        self.course = CourseFactory.create()

        problem_xml = OptionResponseXMLFactory().build_xml(
            question_text='The correct answer is Correct',
            num_inputs=2,
            weight=2,
            options=['Correct', 'Incorrect'],
            correct_option='Correct')
        self.descriptor = ItemFactory.create(
            category='problem',
            data=problem_xml,
            display_name='Option Response Problem')

        self.location = self.descriptor.location
        self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id, self.user, self.descriptor)