def test_db_model_keys(): # Tests that updates to fields are properly recorded in the KeyValueStore, # and that the keys have been constructed correctly key_store = DictKeyValueStore() field_data = KvsFieldData(key_store) runtime = TestRuntime(Mock(), mixins=[TestMixin], services={'field-data': field_data}) tester = runtime.construct_xblock_from_class(TestXBlock, ScopeIds('s0', 'TestXBlock', 'd0', 'u0')) assert not field_data.has(tester, 'not a field') for field in six.itervalues(tester.fields): new_value = 'new ' + field.name assert not field_data.has(tester, field.name) if isinstance(field, List): new_value = [new_value] setattr(tester, field.name, new_value) # Write out the values tester.save() # Make sure everything saved correctly for field in six.itervalues(tester.fields): assert field_data.has(tester, field.name) def get_key_value(scope, user_id, block_scope_id, field_name): """Gets the value, from `key_store`, of a Key with the given values.""" new_key = KeyValueStore.Key(scope, user_id, block_scope_id, field_name) return key_store.db_dict[new_key] # Examine each value in the database and ensure that keys were constructed correctly assert get_key_value(Scope.content, None, 'd0', 'content') == 'new content' assert get_key_value(Scope.settings, None, 'u0', 'settings') == 'new settings' assert get_key_value(Scope.user_state, 's0', 'u0', 'user_state') == 'new user_state' assert get_key_value(Scope.preferences, 's0', 'TestXBlock', 'preferences') == 'new preferences' assert get_key_value(Scope.user_info, 's0', None, 'user_info') == 'new user_info' assert get_key_value(Scope(UserScope.NONE, BlockScope.TYPE), None, 'TestXBlock', 'by_type') == 'new by_type' assert get_key_value(Scope(UserScope.NONE, BlockScope.ALL), None, None, 'for_all') == 'new for_all' assert get_key_value(Scope(UserScope.ONE, BlockScope.DEFINITION), 's0', 'd0', 'user_def') == 'new user_def' assert get_key_value(Scope(UserScope.ALL, BlockScope.ALL), None, None, 'agg_global') == 'new agg_global' assert get_key_value(Scope(UserScope.ALL, BlockScope.TYPE), None, 'TestXBlock', 'agg_type') == 'new agg_type' assert get_key_value(Scope(UserScope.ALL, BlockScope.DEFINITION), None, 'd0', 'agg_def') == 'new agg_def' assert get_key_value(Scope.user_state_summary, None, 'u0', 'agg_usage') == 'new agg_usage' assert get_key_value(Scope.content, None, 'd0', 'mixin_content') == 'new mixin_content' assert get_key_value(Scope.settings, None, 'u0', 'mixin_settings') == 'new mixin_settings' assert get_key_value(Scope.user_state, 's0', 'u0', 'mixin_user_state') == 'new mixin_user_state' assert get_key_value(Scope.preferences, 's0', 'TestXBlock', 'mixin_preferences') == 'new mixin_preferences' assert get_key_value(Scope.user_info, 's0', None, 'mixin_user_info') == 'new mixin_user_info' assert get_key_value(Scope(UserScope.NONE, BlockScope.TYPE), None, 'TestXBlock', 'mixin_by_type') == \ 'new mixin_by_type' assert get_key_value(Scope(UserScope.NONE, BlockScope.ALL), None, None, 'mixin_for_all') == \ 'new mixin_for_all' assert get_key_value(Scope(UserScope.ONE, BlockScope.DEFINITION), 's0', 'd0', 'mixin_user_def') == \ 'new mixin_user_def' assert get_key_value(Scope(UserScope.ALL, BlockScope.ALL), None, None, 'mixin_agg_global') == \ 'new mixin_agg_global' assert get_key_value(Scope(UserScope.ALL, BlockScope.TYPE), None, 'TestXBlock', 'mixin_agg_type') == \ 'new mixin_agg_type' assert get_key_value(Scope(UserScope.ALL, BlockScope.DEFINITION), None, 'd0', 'mixin_agg_def') == \ 'new mixin_agg_def' assert get_key_value(Scope.user_state_summary, None, 'u0', 'mixin_agg_usage') == 'new mixin_agg_usage'
def setUp(self): """ Create a stub XBlock backed by in-memory storage. """ self.runtime = mock.MagicMock(Runtime) self.field_data = KvsFieldData(kvs=DictKeyValueStore()) self.scope_ids = ScopeIds('Bob', 'stubxblock', '123', 'import') self.xblock = StubXBlock(self.runtime, self.field_data, self.scope_ids) super(RemapNamespaceTest, self).setUp()
def make_xblock(self, **kwargs): key_store = DictKeyValueStore() field_data = KvsFieldData(key_store) runtime = TestRuntime(services={'field-data': field_data}) xblock = WistiaVideoXBlock(runtime, scope_ids=Mock()) for attr, val in kwargs.items(): setattr(xblock, attr, val) return xblock
def _prepare_asides(self, scope_ids): """ Return list with connected aside xblocks """ key_store = DictKeyValueStore() field_data = KvsFieldData(key_store) aside = AsideTest(scope_ids=scope_ids, runtime=TestRuntime(services={'field-data': field_data})) # pylint: disable=abstract-class-instantiated aside.fields[self.ASIDE_DATA_FIELD.field_name].write_to(aside, self.ASIDE_DATA_FIELD.initial) return [aside]
def setUp(self): block_type = 'hastexo' key_store = DictKeyValueStore() field_data = KvsFieldData(key_store) runtime = WorkbenchRuntime() def_id = runtime.id_generator.create_definition(block_type) usage_id = runtime.id_generator.create_usage(def_id) scope_ids = ScopeIds('user', block_type, def_id, usage_id) self.block = HastexoXBlock(runtime, field_data, scope_ids=scope_ids)
def make_block(): """ Instantiate a DragAndDropBlock XBlock inside a WorkbenchRuntime """ block_type = 'drag_and_drop_v2' key_store = DictKeyValueStore() field_data = KvsFieldData(key_store) runtime = WorkbenchRuntime() def_id = runtime.id_generator.create_definition(block_type) usage_id = runtime.id_generator.create_usage(def_id) scope_ids = ScopeIds('user', block_type, def_id, usage_id) return drag_and_drop_v2.DragAndDropBlock(runtime, field_data, scope_ids=scope_ids)
def load_item(self, location): """ Return an XModule instance for the specified location """ location = Location(location) json_data = self.module_data.get(location) if json_data is None: module = self.modulestore.get_item(location) if module is not None: # update our own cache after going to the DB to get cache miss self.module_data.update(module.runtime.module_data) return module else: # load the module and apply the inherited metadata try: category = json_data['location']['category'] class_ = self.load_block_type(category) definition = json_data.get('definition', {}) metadata = json_data.get('metadata', {}) for old_name, new_name in getattr(class_, 'metadata_translations', {}).items(): if old_name in metadata: metadata[new_name] = metadata[old_name] del metadata[old_name] kvs = MongoKeyValueStore( definition.get('data', {}), definition.get('children', []), metadata, ) field_data = KvsFieldData(kvs) scope_ids = ScopeIds(None, category, location, location) module = self.construct_xblock_from_class(class_, scope_ids, field_data) if self.cached_metadata is not None: # parent container pointers don't differentiate between draft and non-draft # so when we do the lookup, we should do so with a non-draft location non_draft_loc = location.replace(revision=None) # Convert the serialized fields values in self.cached_metadata # to python values metadata_to_inherit = self.cached_metadata.get(non_draft_loc.url(), {}) inherit_metadata(module, metadata_to_inherit) # decache any computed pending field settings module.save() return module except: log.warning("Failed to load descriptor", exc_info=True) return ErrorDescriptor.from_json( json_data, self, json_data['location'], error_msg=exc_info_to_str(sys.exc_info()) )
def make_block(self): block_type = 'diagnostic_feedback' key_store = DictKeyValueStore() field_data = KvsFieldData(key_store) runtime = WorkbenchRuntime() def_id = runtime.id_generator.create_definition(block_type) usage_id = runtime.id_generator.create_usage(def_id) scope_ids = ScopeIds('user', block_type, def_id, usage_id) return diagnostic_feedback.QuizBlock(runtime, field_data, scope_ids=scope_ids)
def __init__(self, user_id=None): # TODO: Add params for user, runtime, etc. to service initialization # Move to stevedor super(WorkbenchRuntime, self).__init__(ID_MANAGER, services={ 'fs': xblock.reference.plugins.FSService(), 'field-data': KvsFieldData(WORKBENCH_KVS), }) self.id_generator = ID_MANAGER self.user_id = user_id
def __init__( self, handler_url, # type: (Callable[[XBlock, string, string, string, bool], string] authored_data_kvs, # type: KeyValueStore student_data_kvs, # type: KeyValueStore runtime_class, # type: XBlockRuntime ): """ args: handler_url: A method that implements the XBlock runtime handler_url interface. authored_data_kvs: An KeyValueStore used to retrieve any fields with UserScope.NONE student_data_kvs: An KeyValueStore used to retrieve any fields with UserScope.ONE or UserScope.ALL """ self.handler_url = handler_url # TODO: new ID manager: self.id_reader = OpaqueKeyReader() self.id_generator = MemoryIdManager( ) # We don't really use id_generator until we need to support asides self.runtime_class = runtime_class # Field data storage/retrieval: authored_data = KvsFieldData(kvs=authored_data_kvs) student_data = KvsFieldData(kvs=student_data_kvs) #if authored_data_readonly: # authored_data = ReadOnlyFieldData(authored_data) self.field_data = SplitFieldData({ Scope.content: authored_data, Scope.settings: authored_data, Scope.parent: authored_data, Scope.children: authored_data, Scope.user_state_summary: student_data, Scope.user_state: student_data, Scope.user_info: student_data, Scope.preferences: student_data, }) self._error_trackers = {}
def setUp(self): field_data = KvsFieldData(DictKeyValueStore()) runtime = TestRuntime(services={ 'settings': MockService(OoyalaPlayerBlock, self.XBLOCK_SETTINGS) }) self.player = OoyalaPlayerBlock(runtime, field_data, scope_ids=Mock(spec=ScopeIds)) self.player.DEFAULT_ATTRIBUTE_SETTINGS = { self.REAL_ATTRIBUTE: self.DEFAULT_SETTING_NAME }
def _create_new_field_data(self, category, location, definition_data, metadata): """ To instantiate a new xmodule which will be saved latter, set up the dbModel and kvs """ kvs = MongoKeyValueStore( definition_data, [], metadata, ) field_data = KvsFieldData(kvs) return field_data
def test_default_fn(): key_store = SerialDefaultKVS() db_model = KvsFieldData(key_store) tester = TestIntegerXblock(Mock(), db_model, Mock()) tester2 = TestIntegerXblock(Mock(), db_model, Mock()) # ensure value is not in tester before any actions assert_false(db_model.has(tester, 'counter')) # ensure value is same over successive calls for same DbModel first_call = tester.counter assert_equals(first_call, 1) assert_equals(first_call, tester.counter) # ensure the value is not saved in the object assert_false(db_model.has(tester, 'counter')) # ensure save does not save the computed default back to the object tester.save() assert_false(db_model.has(tester, 'counter')) # ensure second object gets another value second_call = tester2.counter assert_equals(second_call, 2)
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 _init_field_data_for_block(self, block): """ Initialize the FieldData implementation for the specified XBlock """ if self.user is None: # No user is specified, so we want to throw an error if anything attempts to read/write user-specific fields student_data_store = None elif self.user.is_anonymous: # This is an anonymous (non-registered) user: assert self.user_id.startswith("anon") kvs = EphemeralKeyValueStore() student_data_store = KvsFieldData(kvs) elif self.system.student_data_mode == XBlockRuntimeSystem.STUDENT_DATA_EPHEMERAL: # We're in an environment like Studio where we want to let the # author test blocks out but not permanently save their state. kvs = EphemeralKeyValueStore() student_data_store = KvsFieldData(kvs) else: # Use database-backed field data (i.e. store user_state in StudentModule) context_key = block.scope_ids.usage_id.context_key if context_key not in self.django_field_data_caches: field_data_cache = FieldDataCache( [block], course_id=context_key, user=self.user, asides=None, read_only=False, ) self.django_field_data_caches[context_key] = field_data_cache else: field_data_cache = self.django_field_data_caches[context_key] field_data_cache.add_descriptors_to_cache([block]) student_data_store = KvsFieldData(kvs=DjangoKeyValueStore(field_data_cache)) return SplitFieldData({ Scope.content: self.system.authored_data_store, Scope.settings: self.system.authored_data_store, Scope.parent: self.system.authored_data_store, Scope.children: self.system.children_data_store, Scope.user_state_summary: student_data_store, Scope.user_state: student_data_store, Scope.user_info: student_data_store, Scope.preferences: student_data_store, })
def test_default_fn(): key_store = SerialDefaultKVS() field_data = KvsFieldData(key_store) runtime = TestRuntime(services={'field-data': field_data}) tester = TestIntegerXblock(runtime, scope_ids=Mock(spec=ScopeIds)) tester2 = TestIntegerXblock(runtime, scope_ids=Mock(spec=ScopeIds)) # ensure value is not in tester before any actions assert_false(field_data.has(tester, 'counter')) # ensure value is same over successive calls for same DbModel first_call = tester.counter assert_equals(first_call, 1) assert_equals(first_call, tester.counter) # ensure the value is not saved in the object assert_false(field_data.has(tester, 'counter')) # ensure save does not save the computed default back to the object tester.save() assert_false(field_data.has(tester, 'counter')) # ensure second object gets another value second_call = tester2.counter assert_equals(second_call, 2)
def _load_preview_module(request, descriptor): """ Return a preview XModule instantiated from the supplied descriptor. request: The active django request descriptor: An XModuleDescriptor """ student_data = KvsFieldData(SessionKeyValueStore(request)) descriptor.bind_for_student( _preview_module_system(request, descriptor), LmsFieldData(descriptor._field_data, student_data), # pylint: disable=protected-access ) return descriptor
def test_inherited_field(self): kvs = InheritanceKeyValueStore(initial_values={}, inherited_settings={'showanswer': 'inherited'}) model_data = KvsFieldData(kvs) descriptor = self.get_descriptor(model_data) editable_fields = descriptor.editable_metadata_fields self.assert_field_values( editable_fields, 'showanswer', InheritanceMixin.showanswer, explicitly_set=False, value='inherited', default_value='inherited' ) # Mimic the case where display_name WOULD have been inherited, except we explicitly set it. kvs = InheritanceKeyValueStore( initial_values={'showanswer': 'explicit'}, inherited_settings={'showanswer': 'inheritable value'} ) model_data = KvsFieldData(kvs) descriptor = self.get_descriptor(model_data) editable_fields = descriptor.editable_metadata_fields self.assert_field_values( editable_fields, 'showanswer', InheritanceMixin.showanswer, explicitly_set=True, value='explicit', default_value='inheritable value' )
def test_aside_contains_tags(self): """ Checks that available_tags list is not empty """ sids = ScopeIds(user_id="bob", block_type="bobs-type", def_id="definition-id", usage_id="usage-id") key_store = DictKeyValueStore() field_data = KvsFieldData(key_store) runtime = TestRuntime(services={'field-data': field_data}) # pylint: disable=abstract-class-instantiated xblock_aside = StructuredTagsAside(scope_ids=sids, runtime=runtime) available_tags = xblock_aside.get_available_tags() self.assertEquals(len(available_tags), 2, "StructuredTagsAside should contains two tag categories")
def __init__(self, user_id=None): # TODO: Add params for user, runtime, etc. to service initialization # Move to stevedor services={ 'field-data': KvsFieldData(WORKBENCH_KVS), 'user': WorkBenchUserService(user_id), } if hasattr(xblock.reference.plugins, 'FSService'): services['fs'] = xblock.reference.plugins.FSService() super(WorkbenchRuntime, self).__init__(ID_MANAGER, services=services) self.id_generator = ID_MANAGER self.user_id = user_id
def test_view_counter_state(): key_store = DictKeyValueStore() field_data = KvsFieldData(key_store) runtime = Runtime(services={'field-data': field_data}) tester = ViewCounter(runtime, scope_ids=Mock()) assert tester.views == 0 # View the XBlock five times for i in range(5): generated_html = tester.student_view({}) # Make sure the html fragment we're expecting appears in the body_html assert f'<span class="views">{i + 1}</span>' in generated_html.body_html() assert tester.views == (i + 1)
def test_view_counter_state(): key_store = DictKeyValueStore() db_model = KvsFieldData(key_store) tester = ViewCounter(Mock(), db_model, Mock()) assert_equals(tester.views, 0) # View the XBlock five times for i in xrange(5): generated_html = tester.student_view({}) # Make sure the html fragment we're expecting appears in the body_html assert_in('<span class="views">{0}</span>'.format(i + 1), generated_html.body_html()) assert_equals(tester.views, i + 1)
def setUp(self): """ Create a stub XBlock backed by in-memory storage. """ self.runtime = mock.MagicMock(Runtime) self.field_data = KvsFieldData(kvs=DictKeyValueStore()) self.scope_ids = ScopeIds('Bob', 'mutablestubxblock', '123', 'import') self.xblock = StubXBlockWithMutableFields(self.runtime, self.field_data, self.scope_ids) self.fake_children_locations = [ BlockUsageLocator(CourseLocator('org', 'course', 'run'), 'mutablestubxblock', 'child1'), BlockUsageLocator(CourseLocator('org', 'course', 'run'), 'mutablestubxblock', 'child2'), ] super(UpdateLocationTest, self).setUp()
def _load_preview_module(request, descriptor): """ Return a preview XModule instantiated from the supplied descriptor. Will use mutable fields if XModule supports an author_view. Otherwise, will use immutable fields and student_view. request: The active django request descriptor: An XModuleDescriptor """ student_data = KvsFieldData(SessionKeyValueStore(request)) if _has_author_view(descriptor): field_data = CmsFieldData(descriptor._field_data, student_data) # pylint: disable=protected-access else: field_data = LmsFieldData(descriptor._field_data, student_data) # pylint: disable=protected-access descriptor.bind_for_student(_preview_module_system(request, descriptor), field_data) return descriptor
def __init__(self, load_error_modules): xmlstore = XMLModuleStore("data_dir", source_dirs=[], load_error_modules=load_error_modules) course_id = CourseKey.from_string('/'.join([ORG, COURSE, 'test_run'])) course_dir = "test_dir" error_tracker = Mock() super(DummySystem, self).__init__( xmlstore=xmlstore, course_id=course_id, course_dir=course_dir, error_tracker=error_tracker, load_error_modules=load_error_modules, field_data=KvsFieldData(DictKeyValueStore()), )
def make_xblock(xblock_name, xblock_cls, attributes): """ Helper to construct XBlock objects """ runtime = WorkbenchRuntime() key_store = DictKeyValueStore() db_model = KvsFieldData(key_store) ids = generate_scope_ids(runtime, xblock_name) xblock = xblock_cls(runtime, db_model, scope_ids=ids) xblock.category = Mock() xblock.location = Mock(html_id=Mock(return_value='sample_element_id'), ) xblock.runtime = Mock(hostname='localhost', ) xblock.course_id = 'course-v1:edX+DemoX+Demo_Course' for key, value in attributes.items(): setattr(xblock, key, value) return xblock
def __init__(self, load_error_modules, course_id=None): xmlstore = XMLModuleStore("data_dir", source_dirs=[], load_error_modules=load_error_modules) if course_id is None: course_id = CourseKey.from_string('/'.join([ORG, COURSE, 'test_run'])) course_dir = "test_dir" error_tracker = Mock() super(DummySystem, self).__init__( # lint-amnesty, pylint: disable=super-with-arguments xmlstore=xmlstore, course_id=course_id, course_dir=course_dir, error_tracker=error_tracker, load_error_modules=load_error_modules, field_data=KvsFieldData(DictKeyValueStore()), )
def __init__(self, load_error_modules): xmlstore = XMLModuleStore("data_dir", course_dirs=[], load_error_modules=load_error_modules) course_id = SlashSeparatedCourseKey(ORG, COURSE, 'test_run') course_dir = "test_dir" error_tracker = Mock() super(DummySystem, self).__init__( xmlstore=xmlstore, course_id=course_id, course_dir=course_dir, error_tracker=error_tracker, load_error_modules=load_error_modules, field_data=KvsFieldData(DictKeyValueStore()), )
def __init__(self, load_error_modules): xmlstore = XMLModuleStore("data_dir", course_dirs=[], load_error_modules=load_error_modules) course_id = "/".join([ORG, COURSE, 'test_run']) course_dir = "test_dir" error_tracker = Mock() parent_tracker = Mock() super(DummySystem, self).__init__( xmlstore=xmlstore, course_id=course_id, course_dir=course_dir, error_tracker=error_tracker, parent_tracker=parent_tracker, load_error_modules=load_error_modules, field_data=KvsFieldData(DictKeyValueStore()), id_reader=LocationReader(), )
def get_module_for_descriptor(user, request, descriptor, field_data_cache, course_key, position=None, wrap_xmodule_display=True, grade_bucket_type=None, static_asset_path='', disable_staff_debug_info=False, course=None): """ Implements get_module, extracting out the request-specific functionality. disable_staff_debug_info : If this is True, exclude staff debug information in the rendering of the module. See get_module() docstring for further details. """ track_function = make_track_function(request) xqueue_callback_url_prefix = get_xqueue_callback_url_prefix(request) user_location = getattr(request, 'session', {}).get('country_code') student_kvs = DjangoKeyValueStore(field_data_cache) if is_masquerading_as_specific_student(user, course_key): student_kvs = MasqueradingKeyValueStore(student_kvs, request.session) student_data = KvsFieldData(student_kvs) return get_module_for_descriptor_internal( user=user, descriptor=descriptor, student_data=student_data, course_id=course_key, 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=xblock_request_token(request), disable_staff_debug_info=disable_staff_debug_info, course=course)
def __init__(self, load_error_modules, library=False): if library: xmlstore = LibraryXMLModuleStore("data_dir", source_dirs=[], load_error_modules=load_error_modules) else: xmlstore = XMLModuleStore("data_dir", source_dirs=[], load_error_modules=load_error_modules) course_id = SlashSeparatedCourseKey(ORG, COURSE, 'test_run') course_dir = "test_dir" error_tracker = Mock() super(DummySystem, self).__init__( xmlstore=xmlstore, course_id=course_id, course_dir=course_dir, error_tracker=error_tracker, load_error_modules=load_error_modules, mixins=(InheritanceMixin, XModuleMixin), field_data=KvsFieldData(DictKeyValueStore()), )
def test_db_model_keys(): # Tests that updates to fields are properly recorded in the KeyValueStore, # and that the keys have been constructed correctly key_store = DictKeyValueStore() field_data = KvsFieldData(key_store) runtime = TestRuntime(Mock(), mixins=[TestMixin], services={"field-data": field_data}) tester = runtime.construct_xblock_from_class(TestXBlock, ScopeIds("s0", "TestXBlock", "d0", "u0")) assert_false(field_data.has(tester, "not a field")) for field in tester.fields.values(): new_value = "new " + field.name assert_false(field_data.has(tester, field.name)) if isinstance(field, List): new_value = [new_value] setattr(tester, field.name, new_value) # Write out the values tester.save() # Make sure everything saved correctly for field in tester.fields.values(): assert_true(field_data.has(tester, field.name)) def get_key_value(scope, user_id, block_scope_id, field_name): """Gets the value, from `key_store`, of a Key with the given values.""" new_key = KeyValueStore.Key(scope, user_id, block_scope_id, field_name) return key_store.db_dict[new_key] # Examine each value in the database and ensure that keys were constructed correctly assert_equals("new content", get_key_value(Scope.content, None, "d0", "content")) assert_equals("new settings", get_key_value(Scope.settings, None, "u0", "settings")) assert_equals("new user_state", get_key_value(Scope.user_state, "s0", "u0", "user_state")) assert_equals("new preferences", get_key_value(Scope.preferences, "s0", "TestXBlock", "preferences")) assert_equals("new user_info", get_key_value(Scope.user_info, "s0", None, "user_info")) assert_equals("new by_type", get_key_value(Scope(UserScope.NONE, BlockScope.TYPE), None, "TestXBlock", "by_type")) assert_equals("new for_all", get_key_value(Scope(UserScope.NONE, BlockScope.ALL), None, None, "for_all")) assert_equals("new user_def", get_key_value(Scope(UserScope.ONE, BlockScope.DEFINITION), "s0", "d0", "user_def")) assert_equals("new agg_global", get_key_value(Scope(UserScope.ALL, BlockScope.ALL), None, None, "agg_global")) assert_equals("new agg_type", get_key_value(Scope(UserScope.ALL, BlockScope.TYPE), None, "TestXBlock", "agg_type")) assert_equals("new agg_def", get_key_value(Scope(UserScope.ALL, BlockScope.DEFINITION), None, "d0", "agg_def")) assert_equals("new agg_usage", get_key_value(Scope.user_state_summary, None, "u0", "agg_usage")) assert_equals("new mixin_content", get_key_value(Scope.content, None, "d0", "mixin_content")) assert_equals("new mixin_settings", get_key_value(Scope.settings, None, "u0", "mixin_settings")) assert_equals("new mixin_user_state", get_key_value(Scope.user_state, "s0", "u0", "mixin_user_state")) assert_equals("new mixin_preferences", get_key_value(Scope.preferences, "s0", "TestXBlock", "mixin_preferences")) assert_equals("new mixin_user_info", get_key_value(Scope.user_info, "s0", None, "mixin_user_info")) assert_equals( "new mixin_by_type", get_key_value(Scope(UserScope.NONE, BlockScope.TYPE), None, "TestXBlock", "mixin_by_type") ) assert_equals( "new mixin_for_all", get_key_value(Scope(UserScope.NONE, BlockScope.ALL), None, None, "mixin_for_all") ) assert_equals( "new mixin_user_def", get_key_value(Scope(UserScope.ONE, BlockScope.DEFINITION), "s0", "d0", "mixin_user_def") ) assert_equals( "new mixin_agg_global", get_key_value(Scope(UserScope.ALL, BlockScope.ALL), None, None, "mixin_agg_global") ) assert_equals( "new mixin_agg_type", get_key_value(Scope(UserScope.ALL, BlockScope.TYPE), None, "TestXBlock", "mixin_agg_type") ) assert_equals( "new mixin_agg_def", get_key_value(Scope(UserScope.ALL, BlockScope.DEFINITION), None, "d0", "mixin_agg_def") ) assert_equals("new mixin_agg_usage", get_key_value(Scope.user_state_summary, None, "u0", "mixin_agg_usage"))