def update_from_json(cls, descriptor, jsondict, filter_tabs=True): """ Decode the json into CourseMetadata and save any changed attrs to the db. Ensures none of the fields are in the blacklist. """ dirty = False # Copy the filtered list to avoid permanently changing the class attribute. filtered_list = list(cls.FILTERED_LIST) # Don't filter on the tab attribute if filter_tabs is False. if not filter_tabs: filtered_list.remove("tabs") for key, val in jsondict.iteritems(): # should it be an error if one of the filtered list items is in the payload? if key in filtered_list: continue if key == "unsetKeys": dirty = True for unset in val: descriptor.fields[unset].delete_from(descriptor) if hasattr(descriptor, key) and getattr(descriptor, key) != val: dirty = True value = descriptor.fields[key].from_json(val) setattr(descriptor, key, value) if dirty: get_modulestore(descriptor.location).update_metadata( descriptor.location, own_metadata(descriptor)) return cls.fetch(descriptor)
def update_grader_from_json(course_location, grader): """ Create or update the grader of the given type (string key) for the given course. Returns the modified grader which is a full model on the client but not on the server (just a dict) """ course_old_location = loc_mapper().translate_locator_to_location( course_location) descriptor = get_modulestore(course_old_location).get_item( course_old_location) # parse removes the id; so, grab it before parse index = int(grader.get('id', len(descriptor.raw_grader))) grader = CourseGradingModel.parse_grader(grader) if index < len(descriptor.raw_grader): descriptor.raw_grader[index] = grader else: descriptor.raw_grader.append(grader) get_modulestore(course_old_location).update_item( course_old_location, descriptor.get_explicitly_set_fields_by_scope(Scope.content)) return CourseGradingModel.jsonize_grader(index, descriptor.raw_grader[index])
def update_grader_from_json(course_location, grader): """ Create or update the grader of the given type (string key) for the given course. Returns the modified grader which is a full model on the client but not on the server (just a dict) """ if not isinstance(course_location, Location): course_location = Location(course_location) descriptor = get_modulestore(course_location).get_item(course_location) # # ??? it would be good if these had the course_location in them so that they stand alone sufficiently # # but that would require not using CourseDescriptor's field directly. Opinions? # parse removes the id; so, grab it before parse index = int(grader.get('id', len(descriptor.raw_grader))) grader = CourseGradingModel.parse_grader(grader) if index < len(descriptor.raw_grader): descriptor.raw_grader[index] = grader else: descriptor.raw_grader.append(grader) # Save the data that we've just changed to the underlying # MongoKeyValueStore before we update the mongo datastore. descriptor.save() get_modulestore(course_location).update_item( course_location, descriptor._model_data._kvs._data) return CourseGradingModel.jsonize_grader(index, descriptor.raw_grader[index])
def update_from_json(course_locator, jsondict): """ Decode the json into CourseGradingModel and save any changes. Returns the modified model. Probably not the usual path for updates as it's too coarse grained. """ course_old_location = loc_mapper().translate_locator_to_location( course_locator) descriptor = get_modulestore(course_old_location).get_item( course_old_location) graders_parsed = [ CourseGradingModel.parse_grader(jsonele) for jsonele in jsondict['graders'] ] descriptor.raw_grader = graders_parsed descriptor.grade_cutoffs = jsondict['grade_cutoffs'] get_modulestore(course_old_location).update_item( course_old_location, descriptor.get_explicitly_set_fields_by_scope(Scope.content)) CourseGradingModel.update_grace_period_from_json( course_locator, jsondict['grace_period']) return CourseGradingModel.fetch(course_locator)
def component_handler(request, usage_key_string, handler, suffix=''): """ Dispatch an AJAX action to an xblock Args: usage_id: The usage-id of the block to dispatch to handler (str): The handler to execute suffix (str): The remainder of the url to be passed to the handler Returns: :class:`django.http.HttpResponse`: The response from the handler, converted to a django response """ usage_key = UsageKey.from_string(usage_key_string) descriptor = get_modulestore(usage_key).get_item(usage_key) # Let the module handle the AJAX req = django_to_webob_request(request) try: resp = descriptor.handle(handler, req, suffix) except NoSuchHandlerError: log.info("XBlock %s attempted to access missing handler %r", descriptor, handler, exc_info=True) raise Http404 # unintentional update to handle any side effects of handle call; so, request user didn't author # the change get_modulestore(usage_key).update_item(descriptor, None) return webob_to_django_response(resp)
def test_update_section_grader_type(self): # Get the descriptor and the section_grader_type and assert they are the default values descriptor = get_modulestore(self.course.location).get_item( self.course.location) section_grader_type = CourseGradingModel.get_section_grader_type( self.course_locator) self.assertEqual('notgraded', section_grader_type['graderType']) self.assertEqual(None, descriptor.format) self.assertEqual(False, descriptor.graded) # Change the default grader type to Homework, which should also mark the section as graded CourseGradingModel.update_section_grader_type(self.course, 'Homework', self.user) descriptor = get_modulestore(self.course.location).get_item( self.course.location) section_grader_type = CourseGradingModel.get_section_grader_type( self.course_locator) self.assertEqual('Homework', section_grader_type['graderType']) self.assertEqual('Homework', descriptor.format) self.assertEqual(True, descriptor.graded) # Change the grader type back to notgraded, which should also unmark the section as graded CourseGradingModel.update_section_grader_type(self.course, 'notgraded', self.user) descriptor = get_modulestore(self.course.location).get_item( self.course.location) section_grader_type = CourseGradingModel.get_section_grader_type( self.course_locator) self.assertEqual('notgraded', section_grader_type['graderType']) self.assertEqual(None, descriptor.format) self.assertEqual(False, descriptor.graded)
def module_info(request, module_location): location = Location(module_location) # check that logged in user has permissions to this item if not has_access(request.user, location): raise PermissionDenied() real_method = get_request_method(request) rewrite_static_links = request.GET.get('rewrite_url_links', 'True') in ['True', 'true'] logging.debug('rewrite_static_links = {0} {1}'.format( request.GET.get('rewrite_url_links', 'False'), rewrite_static_links)) # check that logged in user has permissions to this item if not has_access(request.user, location): raise PermissionDenied() if real_method == 'GET': return HttpResponse(json.dumps( get_module_info(get_modulestore(location), location, rewrite_static_links=rewrite_static_links)), mimetype="application/json") elif real_method == 'POST' or real_method == 'PUT': return HttpResponse(json.dumps( set_module_info(get_modulestore(location), location, request.POST)), mimetype="application/json") else: return HttpResponseBadRequest()
def test_course_export_success(self): """ Test successful course export response. """ # Build out local bare repo, and set course git url to it repo_dir = os.path.abspath(git_export_utils.GIT_REPO_EXPORT_DIR) os.mkdir(repo_dir) self.addCleanup(shutil.rmtree, repo_dir) bare_repo_dir = '{0}/test_repo.git'.format( os.path.abspath(git_export_utils.GIT_REPO_EXPORT_DIR)) os.mkdir(bare_repo_dir) self.addCleanup(shutil.rmtree, bare_repo_dir) subprocess.check_output([ 'git', '--bare', 'init', ], cwd=bare_repo_dir) self.populate_course() self.course_module.giturl = 'file://{}'.format(bare_repo_dir) get_modulestore(self.course_module.location).update_item( self.course_module) response = self.client.get('{}?action=push'.format(self.test_url)) self.assertIn('Export Succeeded', response.content)
def update_grader_from_json(course_location, grader): """ Create or update the grader of the given type (string key) for the given course. Returns the modified grader which is a full model on the client but not on the server (just a dict) """ if not isinstance(course_location, Location): course_location = Location(course_location) descriptor = get_modulestore(course_location).get_item(course_location) # # ??? it would be good if these had the course_location in them so that they stand alone sufficiently # # but that would require not using CourseDescriptor's field directly. Opinions? # parse removes the id; so, grab it before parse index = int(grader.get('id', len(descriptor.raw_grader))) grader = CourseGradingModel.parse_grader(grader) if index < len(descriptor.raw_grader): descriptor.raw_grader[index] = grader else: descriptor.raw_grader.append(grader) # Save the data that we've just changed to the underlying # MongoKeyValueStore before we update the mongo datastore. descriptor.save() get_modulestore(course_location).update_item(course_location, descriptor._model_data._kvs._data) return CourseGradingModel.jsonize_grader(index, descriptor.raw_grader[index])
def update_grace_period_from_json(course_location, graceperiodjson): """ Update the course's default grace period. Incoming dict is {hours: h, minutes: m} possibly as a grace_period entry in an enclosing dict. It is also safe to call this method with a value of None for graceperiodjson. """ if not isinstance(course_location, Location): course_location = Location(course_location) # Before a graceperiod has ever been created, it will be None (once it has been # created, it cannot be set back to None). if graceperiodjson is not None: if 'grace_period' in graceperiodjson: graceperiodjson = graceperiodjson['grace_period'] # lms requires these to be in a fixed order grace_timedelta = timedelta(**graceperiodjson) descriptor = get_modulestore(course_location).get_item(course_location) descriptor.lms.graceperiod = grace_timedelta # Save the data that we've just changed to the underlying # MongoKeyValueStore before we update the mongo datastore. descriptor.save() get_modulestore(course_location).update_metadata(course_location, descriptor._model_data._kvs._metadata)
def module_info(request, module_location): "Get or set information for a module in the modulestore" location = Location(module_location) # check that logged in user has permissions to this item if not has_access(request.user, location): raise PermissionDenied() rewrite_static_links = request.GET.get('rewrite_url_links', 'True') in ['True', 'true'] logging.debug('rewrite_static_links = {0} {1}'.format( request.GET.get('rewrite_url_links', False), rewrite_static_links) ) # check that logged in user has permissions to this item if not has_access(request.user, location): raise PermissionDenied() if request.method == 'GET': rsp = get_module_info( get_modulestore(location), location, rewrite_static_links=rewrite_static_links ) elif request.method in ("POST", "PUT"): rsp = set_module_info( get_modulestore(location), location, request.POST ) return JsonResponse(rsp)
def update_from_json(cls, descriptor, jsondict, filter_tabs=True, user=None): """ Decode the json into CourseMetadata and save any changed attrs to the db. Ensures none of the fields are in the blacklist. """ dirty = False # Copy the filtered list to avoid permanently changing the class attribute. filtered_list = list(cls.FILTERED_LIST) # Don't filter on the tab attribute if filter_tabs is False. if not filter_tabs: filtered_list.remove("tabs") for key, val in jsondict.iteritems(): # should it be an error if one of the filtered list items is in the payload? if key in filtered_list: continue if key == "unsetKeys": dirty = True for unset in val: descriptor.fields[unset].delete_from(descriptor) if hasattr(descriptor, key) and getattr(descriptor, key) != val: dirty = True value = descriptor.fields[key].from_json(val) setattr(descriptor, key, value) if dirty: get_modulestore(descriptor.location).update_item(descriptor, user.id if user else None) return cls.fetch(descriptor)
def update_grace_period_from_json(course_location, graceperiodjson): """ Update the course's default grace period. Incoming dict is {hours: h, minutes: m} possibly as a grace_period entry in an enclosing dict. It is also safe to call this method with a value of None for graceperiodjson. """ if not isinstance(course_location, Location): course_location = Location(course_location) # Before a graceperiod has ever been created, it will be None (once it has been # created, it cannot be set back to None). if graceperiodjson is not None: if 'grace_period' in graceperiodjson: graceperiodjson = graceperiodjson['grace_period'] # lms requires these to be in a fixed order grace_timedelta = timedelta(**graceperiodjson) descriptor = get_modulestore(course_location).get_item( course_location) descriptor.lms.graceperiod = grace_timedelta # Save the data that we've just changed to the underlying # MongoKeyValueStore before we update the mongo datastore. descriptor.save() get_modulestore(course_location).update_metadata( course_location, descriptor._model_data._kvs._metadata)
def test_update_section_grader_type(self): # Get the descriptor and the section_grader_type and assert they are the default values descriptor = get_modulestore(self.course.location).get_item(self.course.location) section_grader_type = CourseGradingModel.get_section_grader_type(self.course.location) self.assertEqual('Not Graded', section_grader_type['graderType']) self.assertEqual(None, descriptor.format) self.assertEqual(False, descriptor.graded) # Change the default grader type to Homework, which should also mark the section as graded CourseGradingModel.update_section_grader_type(self.course.location, {'graderType': 'Homework'}) descriptor = get_modulestore(self.course.location).get_item(self.course.location) section_grader_type = CourseGradingModel.get_section_grader_type(self.course.location) self.assertEqual('Homework', section_grader_type['graderType']) self.assertEqual('Homework', descriptor.format) self.assertEqual(True, descriptor.graded) # Change the grader type back to Not Graded, which should also unmark the section as graded CourseGradingModel.update_section_grader_type(self.course.location, {'graderType': 'Not Graded'}) descriptor = get_modulestore(self.course.location).get_item(self.course.location) section_grader_type = CourseGradingModel.get_section_grader_type(self.course.location) self.assertEqual('Not Graded', section_grader_type['graderType']) self.assertEqual(None, descriptor.format) self.assertEqual(False, descriptor.graded)
def update_from_json(jsondict): """ Decode the json into CourseGradingModel and save any changes. Returns the modified model. Probably not the usual path for updates as it's too coarse grained. """ course_location = Location(jsondict['course_location']) descriptor = get_modulestore(course_location).get_item(course_location) graders_parsed = [ CourseGradingModel.parse_grader(jsonele) for jsonele in jsondict['graders'] ] descriptor.raw_grader = graders_parsed descriptor.grade_cutoffs = jsondict['grade_cutoffs'] # Save the data that we've just changed to the underlying # MongoKeyValueStore before we update the mongo datastore. descriptor.save() get_modulestore(course_location).update_item( course_location, descriptor.xblock_kvs._data) CourseGradingModel.update_grace_period_from_json( course_location, jsondict['grace_period']) return CourseGradingModel.fetch(course_location)
def test_course_export_failures(self): """ Test failed course export response. """ self.course_module.giturl = 'foobar' get_modulestore(self.course_module.location).update_item(self.course_module) response = self.client.get('{}?action=push'.format(self.test_url)) self.assertIn('Export Failed:', response.content)
def test_exception_translation(self): """ Regression test for making sure errors are properly stringified """ self.course_module.giturl = 'foobar' get_modulestore(self.course_module.location).update_item(self.course_module) response = self.client.get('{}?action=push'.format(self.test_url)) self.assertNotIn('django.utils.functional.__proxy__', response.content)
def test_course_export_failures(self): """ Test failed course export response. """ self.course_module.giturl = 'foobar' get_modulestore(self.course_module.location).update_item( self.course_module) response = self.client.get('{}?action=push'.format(self.test_url)) self.assertIn('Export Failed:', response.content)
def delete_grace_period(course_location): """ Delete the course's default grace period. """ if not isinstance(course_location, Location): course_location = Location(course_location) descriptor = get_modulestore(course_location).get_item(course_location) del descriptor.lms.graceperiod get_modulestore(course_location).update_metadata(course_location, descriptor._model_data._kvs._metadata)
def update_section_grader_type(descriptor, grader_type, user): if grader_type is not None and grader_type != u'notgraded': descriptor.format = grader_type descriptor.graded = True else: del descriptor.format del descriptor.graded get_modulestore(descriptor.location).update_item(descriptor, user.id) return {'graderType': grader_type}
def delete_grace_period(course_location, user): """ Delete the course's grace period. """ course_old_location = loc_mapper().translate_locator_to_location(course_location) descriptor = get_modulestore(course_old_location).get_item(course_old_location) del descriptor.graceperiod get_modulestore(course_old_location).update_item(descriptor, user.id)
def test_exception_translation(self): """ Regression test for making sure errors are properly stringified """ self.course_module.giturl = 'foobar' get_modulestore(self.course_module.location).update_item( self.course_module) response = self.client.get('{}?action=push'.format(self.test_url)) self.assertNotIn('django.utils.functional.__proxy__', response.content)
def delete_cutoffs(course_location, cutoffs): """ Resets the cutoffs to the defaults """ if not isinstance(course_location, Location): course_location = Location(course_location) descriptor = get_modulestore(course_location).get_item(course_location) descriptor.grade_cutoffs = descriptor.defaut_grading_policy["GRADE_CUTOFFS"] get_modulestore(course_location).update_item(course_location, descriptor._model_data._kvs._data) return descriptor.grade_cutoffs
def update_section_grader_type(descriptor, grader_type): if grader_type is not None and grader_type != u'notgraded': descriptor.format = grader_type descriptor.graded = True else: del descriptor.format del descriptor.graded get_modulestore(descriptor.location).update_metadata( descriptor.location, descriptor.get_explicitly_set_fields_by_scope(Scope.settings)) return {'graderType': grader_type}
def set_course_list(request): try: course_id = request.POST.getlist("data[]"); for i in range(len(course_id)): course = modulestore().get_item(Location(course_id[i])) course.display_sort_number=(i+1)*'1' course.save() get_modulestore(Location(course_id[i])).update_metadata(Location(course_id[i]), course._field_data._kvs._metadata) return JsonResponse({"info":"success"}) except: return JsonResponse({"info":"fail"})
def delete_grace_period(course_location): """ Delete the course's grace period. """ course_old_location = loc_mapper().translate_locator_to_location(course_location) descriptor = get_modulestore(course_old_location).get_item(course_old_location) del descriptor.graceperiod get_modulestore(course_old_location).update_metadata( course_old_location, descriptor.get_explicitly_set_fields_by_scope(Scope.settings) )
def update_section_grader_type(descriptor, grader_type): if grader_type is not None and grader_type != u"Not Graded": descriptor.format = grader_type descriptor.graded = True else: del descriptor.format del descriptor.graded get_modulestore(descriptor.location).update_metadata( descriptor.location, descriptor.get_explicitly_set_fields_by_scope(Scope.settings) ) return {'graderType': grader_type}
def update_cutoffs_from_json(course_location, cutoffs, user): """ Create or update the grade cutoffs for the given course. Returns sent in cutoffs (ie., no extra db fetch). """ course_old_location = loc_mapper().translate_locator_to_location(course_location) descriptor = get_modulestore(course_old_location).get_item(course_old_location) descriptor.grade_cutoffs = cutoffs get_modulestore(course_old_location).update_item(descriptor, user.id) return cutoffs
def delete_cutoffs(course_location, cutoffs): """ Resets the cutoffs to the defaults """ if not isinstance(course_location, Location): course_location = Location(course_location) descriptor = get_modulestore(course_location).get_item(course_location) descriptor.grade_cutoffs = descriptor.defaut_grading_policy['GRADE_CUTOFFS'] get_modulestore(course_location).update_item(course_location, descriptor._model_data._kvs._data) return descriptor.grade_cutoffs
def update_section_grader_type(location, jsondict): if not isinstance(location, Location): location = Location(location) descriptor = get_modulestore(location).get_item(location) if "graderType" in jsondict and jsondict["graderType"] != u"Not Graded": descriptor.lms.format = jsondict.get("graderType") descriptor.lms.graded = True else: del descriptor.lms.format del descriptor.lms.graded get_modulestore(location).update_metadata(location, descriptor._model_data._kvs._metadata)
def update_cutoffs_from_json(course_location, cutoffs): """ Create or update the grade cutoffs for the given course. Returns sent in cutoffs (ie., no extra db fetch). """ if not isinstance(course_location, Location): course_location = Location(course_location) descriptor = get_modulestore(course_location).get_item(course_location) descriptor.grade_cutoffs = cutoffs get_modulestore(course_location).update_item(course_location, descriptor._model_data._kvs._data) return cutoffs
def update_section_grader_type(location, jsondict): if not isinstance(location, Location): location = Location(location) descriptor = get_modulestore(location).get_item(location) if 'graderType' in jsondict and jsondict['graderType'] != u"Not Graded": descriptor.lms.format = jsondict.get('graderType') descriptor.lms.graded = True else: del descriptor.lms.format del descriptor.lms.graded get_modulestore(location).update_metadata(location, descriptor._model_data._kvs._metadata)
def delete_grace_period(course_location): """ Delete the course's grace period. """ course_old_location = loc_mapper().translate_locator_to_location( course_location) descriptor = get_modulestore(course_old_location).get_item( course_old_location) del descriptor.graceperiod get_modulestore(course_old_location).update_metadata( course_old_location, descriptor.get_explicitly_set_fields_by_scope(Scope.settings))
def delete_grader(course_location, index): """ Delete the grader of the given type from the given course. """ if not isinstance(course_location, Location): course_location = Location(course_location) descriptor = get_modulestore(course_location).get_item(course_location) index = int(index) if index < len(descriptor.raw_grader): del descriptor.raw_grader[index] # force propagation to definition descriptor.raw_grader = descriptor.raw_grader get_modulestore(course_location).update_item(course_location, descriptor._model_data._kvs._data)
def delete_grace_period(course_location): """ Delete the course's default grace period. """ if not isinstance(course_location, Location): course_location = Location(course_location) descriptor = get_modulestore(course_location).get_item(course_location) del descriptor.lms.graceperiod # Save the data that we've just changed to the underlying # MongoKeyValueStore before we update the mongo datastore. descriptor.save() get_modulestore(course_location).update_metadata(course_location, descriptor._model_data._kvs._metadata)
def update_cutoffs_from_json(course_location, cutoffs): """ Create or update the grade cutoffs for the given course. Returns sent in cutoffs (ie., no extra db fetch). """ course_old_location = loc_mapper().translate_locator_to_location(course_location) descriptor = get_modulestore(course_old_location).get_item(course_old_location) descriptor.grade_cutoffs = cutoffs get_modulestore(course_old_location).update_item( course_old_location, descriptor.get_explicitly_set_fields_by_scope(Scope.content) ) return cutoffs
def delete_grader(course_location, index, user): """ Delete the grader of the given type from the given course. """ course_old_location = loc_mapper().translate_locator_to_location(course_location) descriptor = get_modulestore(course_old_location).get_item(course_old_location) index = int(index) if index < len(descriptor.raw_grader): del descriptor.raw_grader[index] # force propagation to definition descriptor.raw_grader = descriptor.raw_grader get_modulestore(course_old_location).update_item(descriptor, user.id)
def delete_grace_period(course_location): """ Delete the course's default grace period. """ if not isinstance(course_location, Location): course_location = Location(course_location) descriptor = get_modulestore(course_location).get_item(course_location) del descriptor.lms.graceperiod # Save the data that we've just changed to the underlying # MongoKeyValueStore before we update the mongo datastore. descriptor.save() get_modulestore(course_location).update_metadata( course_location, descriptor._model_data._kvs._metadata)
def setUp(self): """ These tests need a user in the DB so that the django Test Client can log them in. They inherit from the ModuleStoreTestCase class so that the mongodb collection will be cleared out before each test case execution and deleted afterwards. """ uname = 'testuser' email = '*****@*****.**' password = '******' # Create the user so we can log them in. self.user = User.objects.create_user(uname, email, password) # Note that we do not actually need to do anything # for registration if we directly mark them active. self.user.is_active = True # Staff has access to view all courses self.user.is_staff = True self.user.save() self.client = AjaxEnabledTestClient() self.client.login(username=uname, password=password) self.course = CourseFactory.create( org='MITx', number='999', display_name='Robot Super Course', ) self.store = get_modulestore(self.course.location)
def xml_only_video(step): # Create a new video *without* metadata. This requires a certain # amount of rummaging to make sure all the correct data is present step.given('I have clicked the new unit button') # Wait for the new unit to be created and to load the page world.wait(1) location = world.scenario_dict['COURSE'].location store = get_modulestore(location) parent_location = store.get_items(Location(category='vertical', revision='draft'))[0].location youtube_id = 'ABCDEFG' world.scenario_dict['YOUTUBE_ID'] = youtube_id # Create a new Video component, but ensure that it doesn't have # metadata. This allows us to test that we are correctly parsing # out XML video = world.ItemFactory.create( parent_location=parent_location, category='video', data='<video youtube="1.00:%s"></video>' % youtube_id ) # Refresh to see the new video reload_the_page(step)
def delete_grader(course_location, index): """ Delete the grader of the given type from the given course. """ course_old_location = loc_mapper().translate_locator_to_location(course_location) descriptor = get_modulestore(course_old_location).get_item(course_old_location) index = int(index) if index < len(descriptor.raw_grader): del descriptor.raw_grader[index] # force propagation to definition descriptor.raw_grader = descriptor.raw_grader get_modulestore(course_old_location).update_item( course_old_location, descriptor.get_explicitly_set_fields_by_scope(Scope.content) )
def fetch_grader(course_location, index): """ Fetch the course's nth grader Returns an empty dict if there's no such grader. """ if not isinstance(course_location, Location): course_location = Location(course_location) descriptor = get_modulestore(course_location).get_item(course_location) # # ??? it would be good if these had the course_location in them so that they stand alone sufficiently # # but that would require not using CourseDescriptor's field directly. Opinions? index = int(index) if len(descriptor.raw_grader) > index: return CourseGradingModel.jsonize_grader(index, descriptor.raw_grader[index]) # return empty model else: return {"id": index, "type": "", "min_count": 0, "drop_count": 0, "short_label": None, "weight": 0 }
def test_get_checklists(self): """ Tests the get checklists method. """ checklists_url = reverse("checklists", kwargs={ 'org': self.course.location.org, 'course': self.course.location.course, 'name': self.course.location.name, }) response = self.client.get(checklists_url) self.assertContains(response, "Getting Started With Studio") # Verify expansion of action URL happened. self.assertContains(response, '/mitX/333/team/Checklists_Course') # Verify persisted checklist does NOT have expanded URL. checklist_0 = self.get_persisted_checklists()[0] self.assertEqual('ManageUsers', get_action_url(checklist_0, 0)) payload = response.content # Now delete the checklists from the course and verify they get repopulated (for courses # created before checklists were introduced). self.course.checklists = None # Save the changed `checklists` to the underlying KeyValueStore before updating the modulestore self.course.save() modulestore = get_modulestore(self.course.location) modulestore.update_metadata(self.course.location, own_metadata(self.course)) self.assertEqual(self.get_persisted_checklists(), None) response = self.client.get(checklists_url) self.assertEqual(payload, response.content)
def setUp(self): CourseTestCase.setUp(self) # add in the full class too import_from_xml(get_modulestore( self.course_location), 'common/test/data/', ['full']) self.fullcourse_location = Location( ['i4x', 'edX', 'full', 'course', '6.002_Spring_2012', None])
def test_initial_grader(self): descriptor = get_modulestore(self.course.location).get_item(self.course.location) test_grader = CourseGradingModel(descriptor) # ??? How much should this test bake in expectations about defaults and thus fail if defaults change? self.assertEqual(self.course.location, test_grader.course_location, "Course locations") self.assertIsNotNone(test_grader.graders, "No graders") self.assertIsNotNone(test_grader.grade_cutoffs, "No cutoffs")
def textbooks_detail_handler(request, tid, tag=None, package_id=None, branch=None, version_guid=None, block=None): """ JSON API endpoint for manipulating a textbook via its internal ID. Used by the Backbone application. GET json: return JSON representation of textbook POST or PUT json: update textbook based on provided information DELETE json: remove textbook """ __, course = _get_locator_and_course(package_id, branch, version_guid, block, request.user) store = get_modulestore(course.location) matching_id = [ tb for tb in course.pdf_textbooks if unicode(tb.get("id")) == unicode(tid) ] if matching_id: textbook = matching_id[0] else: textbook = None if request.method == 'GET': if not textbook: return JsonResponse(status=404) return JsonResponse(textbook) elif request.method in ('POST', 'PUT'): # can be either and sometimes # django is rewriting one to the other try: new_textbook = validate_textbook_json(request.body) except TextbookValidationError as err: return JsonResponse({"error": err.message}, status=400) new_textbook["id"] = tid if textbook: i = course.pdf_textbooks.index(textbook) new_textbooks = course.pdf_textbooks[0:i] new_textbooks.append(new_textbook) new_textbooks.extend(course.pdf_textbooks[i + 1:]) course.pdf_textbooks = new_textbooks else: course.pdf_textbooks.append(new_textbook) store.update_item(course, request.user.id) return JsonResponse(new_textbook, status=201) elif request.method == 'DELETE': if not textbook: return JsonResponse(status=404) i = course.pdf_textbooks.index(textbook) new_textbooks = course.pdf_textbooks[0:i] new_textbooks.extend(course.pdf_textbooks[i + 1:]) course.pdf_textbooks = new_textbooks store.update_item(course, request.user.id) return JsonResponse()
def get_section_grader_type(location): old_location = loc_mapper().translate_locator_to_location(location) descriptor = get_modulestore(old_location).get_item(old_location) return { "graderType": descriptor.format if descriptor.format is not None else 'notgraded', "location": unicode(location), }
def course_audit_api(request, course_id, operation): re_json = {"success": False} request_method = request.method if request_method != "POST": return JsonResponse(re_json) # get course location and module infomation try: course_location_info = course_id.split('.') locator = BlockUsageLocator(package_id=course_id, branch='draft', version_guid=None, block_id=course_location_info[-1]) course_location = loc_mapper().translate_locator_to_location(locator) course_module = get_modulestore(course_location).get_item(course_location) instructors = CourseInstructorRole(locator).users_with_role() if len(instructors) <= 0: return JsonResponse(re_json) user = instructors[0] meta_json = {} if operation == "pass": meta_json["course_audit"] = 1 elif operation == "offline": meta_json["course_audit"] = 0 else: return JsonResponse(re_json) re_json["success"] = True CourseMetadata.update_from_json(course_module, meta_json, True, user) return JsonResponse(re_json) except: return JsonResponse(re_json)
def fetch_grader(course_location, index): """ Fetch the course's nth grader Returns an empty dict if there's no such grader. """ course_old_location = loc_mapper().translate_locator_to_location( course_location) descriptor = get_modulestore(course_old_location).get_item( course_old_location) index = int(index) if len(descriptor.raw_grader) > index: return CourseGradingModel.jsonize_grader( index, descriptor.raw_grader[index]) # return empty model else: return { "id": index, "type": "", "min_count": 0, "drop_count": 0, "short_label": None, "weight": 0 }
def xml_only_video(step): # Create a new video *without* metadata. This requires a certain # amount of rummaging to make sure all the correct data is present step.given('I have clicked the new unit button') # Wait for the new unit to be created and to load the page world.wait(1) course = world.scenario_dict['COURSE'] store = get_modulestore(course.location) parent_location = store.get_items(course.id, category='vertical', revision='draft')[0].location youtube_id = 'ABCDEFG' world.scenario_dict['YOUTUBE_ID'] = youtube_id # Create a new Video component, but ensure that it doesn't have # metadata. This allows us to test that we are correctly parsing # out XML world.ItemFactory.create( parent_location=parent_location, category='video', data='<video youtube="1.00:%s"></video>' % youtube_id, modulestore=store, )
def create_textbook(request, org, course, name): """ JSON API endpoint for creating a textbook. Used by the Backbone application. """ location = get_location_and_verify_access(request, org, course, name) store = get_modulestore(location) course_module = store.get_item(location, depth=0) try: textbook = validate_textbook_json(request.body) except TextbookValidationError as err: return JsonResponse({"error": err.message}, status=400) if not textbook.get("id"): tids = set(t["id"] for t in course_module.pdf_textbooks if "id" in t) textbook["id"] = assign_textbook_id(textbook, tids) existing = course_module.pdf_textbooks existing.append(textbook) course_module.pdf_textbooks = existing if not any(tab['type'] == 'pdf_textbooks' for tab in course_module.tabs): tabs = course_module.tabs tabs.append({"type": "pdf_textbooks"}) course_module.tabs = tabs # Save the data that we've just changed to the underlying # MongoKeyValueStore before we update the mongo datastore. course_module.save() store.update_metadata(course_module.location, own_metadata(course_module)) resp = JsonResponse(textbook, status=201) resp["Location"] = reverse("textbook_by_id", kwargs={ 'org': org, 'course': course, 'name': name, 'tid': textbook["id"], }) return resp