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 )
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)
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)
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)
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
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)
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
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)
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)
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
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 )
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)
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)
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))
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 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)
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)
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
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
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
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')
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
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
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, )
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')
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)
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, )
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), })
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)
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
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)
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
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)
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
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))
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
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
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, )
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)