def setUp(self): self.content = Mock() self.settings = Mock() self.split = SplitFieldData({ Scope.content: self.content, Scope.settings: self.settings }) self.runtime = TestRuntime(services={'field-data': self.split}) self.block = TestingBlock( runtime=self.runtime, scope_ids=Mock(), )
def setUp(self): self.content = Mock() self.settings = Mock() self.split = SplitFieldData({ Scope.content: self.content, Scope.settings: self.settings }) self.block = TestingBlock( runtime=Mock(), field_data=self.split, scope_ids=Mock(), )
def setup_method(self): """ Setup for each test case in this class. """ self.content = Mock() self.settings = Mock() self.split = SplitFieldData({ Scope.content: self.content, Scope.settings: self.settings }) self.runtime = TestRuntime(services={'field-data': self.split}) self.block = TestingBlock( runtime=self.runtime, scope_ids=Mock(), )
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: # The user is anonymous. Future work will support saving their state # in a cache or the django session but for now just use a highly # ephemeral dict. student_data_store = KvsFieldData(kvs=DictKeyValueStore()) 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. # This in-memory dict will typically only persist for one # request-response cycle, so we need to soon replace it with a store # that puts the state into a cache or the django session. student_data_store = KvsFieldData(kvs=DictKeyValueStore()) 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.authored_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 _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 __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 __init__( self, handler_url, # type: (Callable[[UsageKey, str, Union[int, ANONYMOUS_USER]], str] authored_data_store, # type: FieldData student_data_store, # type: FieldData runtime_class, # type: XBlockRuntime ): """ args: handler_url: A method to get URLs to call XBlock handlers. It must implement this signature: handler_url( usage_key: UsageKey, handler_name: str, user_id: Union[int, ANONYMOUS_USER], ) If user_id is ANONYMOUS_USER, the handler should execute without any user-scoped fields. authored_data_store: A FieldData instance used to retrieve/write any fields with UserScope.NONE student_data_store: A FieldData instance used to retrieve/write any fields with UserScope.ONE or UserScope.ALL """ self.handler_url = handler_url 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 self.authored_data_store = authored_data_store self.field_data = SplitFieldData({ Scope.content: authored_data_store, Scope.settings: authored_data_store, Scope.parent: authored_data_store, Scope.children: authored_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, }) self._error_trackers = {}
class TestSplitFieldData: """ Tests of :ref:`SplitFieldData`. """ # pylint: disable=attribute-defined-outside-init def setup_method(self): """ Setup for each test case in this class. """ self.content = Mock() self.settings = Mock() self.split = SplitFieldData({ Scope.content: self.content, Scope.settings: self.settings }) self.runtime = TestRuntime(services={'field-data': self.split}) self.block = TestingBlock( runtime=self.runtime, scope_ids=Mock(), ) # pylint: enable=attribute-defined-outside-init def test_get(self): self.split.get(self.block, 'content') self.content.get.assert_called_once_with(self.block, 'content') assert not self.settings.get.called def test_set(self): self.split.set(self.block, 'content', 'foo') self.content.set.assert_called_once_with(self.block, 'content', 'foo') assert not self.settings.set.called def test_delete(self): self.split.delete(self.block, 'content') self.content.delete.assert_called_once_with(self.block, 'content') assert not self.settings.delete.called def test_has(self): self.split.has(self.block, 'content') self.content.has.assert_called_once_with(self.block, 'content') assert not self.settings.has.called def test_set_many(self): self.split.set_many(self.block, { 'content': 'new content', 'settings': 'new settings' }) self.content.set_many.assert_called_once_with( self.block, {'content': 'new content'}) self.settings.set_many.assert_called_once_with( self.block, {'settings': 'new settings'}) def test_invalid_scope(self): with pytest.raises(InvalidScopeError): self.split.get(self.block, 'user_state') def test_default(self): self.split.default(self.block, 'content') self.content.default.assert_called_once_with(self.block, 'content') assert not self.settings.default.called
class TestSplitFieldData(object): """ Tests of :ref:`SplitFieldData`. """ def setUp(self): self.content = Mock() self.settings = Mock() self.split = SplitFieldData({ Scope.content: self.content, Scope.settings: self.settings }) self.block = TestingBlock( runtime=Mock(), field_data=self.split, scope_ids=Mock(), ) def test_get(self): self.split.get(self.block, 'content') self.content.get.assert_called_once_with(self.block, 'content') assert_false(self.settings.get.called) def test_set(self): self.split.set(self.block, 'content', 'foo') self.content.set.assert_called_once_with(self.block, 'content', 'foo') assert_false(self.settings.set.called) def test_delete(self): self.split.delete(self.block, 'content') self.content.delete.assert_called_once_with(self.block, 'content') assert_false(self.settings.delete.called) def test_has(self): self.split.has(self.block, 'content') self.content.has.assert_called_once_with(self.block, 'content') assert_false(self.settings.has.called) def test_set_many(self): self.split.set_many(self.block, {'content': 'new content', 'settings': 'new settings'}) self.content.set_many.assert_called_once_with(self.block, {'content': 'new content'}) self.settings.set_many.assert_called_once_with(self.block, {'settings': 'new settings'}) def test_invalid_scope(self): with assert_raises(InvalidScopeError): self.split.get(self.block, 'user_state') def test_default(self): self.split.default(self.block, 'content') self.content.default.assert_called_once_with(self.block, 'content') assert_false(self.settings.default.called)
class TestSplitFieldData(object): """ Tests of :ref:`SplitFieldData`. """ def setUp(self): self.content = Mock() self.settings = Mock() self.split = SplitFieldData({ Scope.content: self.content, Scope.settings: self.settings }) self.block = TestingBlock( runtime=Mock(), field_data=self.split, scope_ids=Mock(), ) def test_get(self): self.split.get(self.block, 'content') self.content.get.assert_called_once_with(self.block, 'content') assert_false(self.settings.get.called) def test_set(self): self.split.set(self.block, 'content', 'foo') self.content.set.assert_called_once_with(self.block, 'content', 'foo') assert_false(self.settings.set.called) def test_delete(self): self.split.delete(self.block, 'content') self.content.delete.assert_called_once_with(self.block, 'content') assert_false(self.settings.delete.called) def test_has(self): self.split.has(self.block, 'content') self.content.has.assert_called_once_with(self.block, 'content') assert_false(self.settings.has.called) def test_set_many(self): self.split.set_many(self.block, { 'content': 'new content', 'settings': 'new settings' }) self.content.set_many.assert_called_once_with( self.block, {'content': 'new content'}) self.settings.set_many.assert_called_once_with( self.block, {'settings': 'new settings'}) def test_invalid_scope(self): with assert_raises(InvalidScopeError): self.split.get(self.block, 'user_state') def test_default(self): self.split.default(self.block, 'content') self.content.default.assert_called_once_with(self.block, 'content') assert_false(self.settings.default.called)
class TestSplitFieldData(object): """ Tests of :ref:`SplitFieldData`. """ # pylint: disable=attribute-defined-outside-init def setup_method(self): """ Setup for each test case in this class. """ self.content = Mock() self.settings = Mock() self.split = SplitFieldData({ Scope.content: self.content, Scope.settings: self.settings }) self.runtime = TestRuntime(services={'field-data': self.split}) self.block = TestingBlock( runtime=self.runtime, scope_ids=Mock(), ) # pylint: enable=attribute-defined-outside-init def test_get(self): self.split.get(self.block, 'content') self.content.get.assert_called_once_with(self.block, 'content') assert not self.settings.get.called def test_set(self): self.split.set(self.block, 'content', 'foo') self.content.set.assert_called_once_with(self.block, 'content', 'foo') assert not self.settings.set.called def test_delete(self): self.split.delete(self.block, 'content') self.content.delete.assert_called_once_with(self.block, 'content') assert not self.settings.delete.called def test_has(self): self.split.has(self.block, 'content') self.content.has.assert_called_once_with(self.block, 'content') assert not self.settings.has.called def test_set_many(self): self.split.set_many(self.block, {'content': 'new content', 'settings': 'new settings'}) self.content.set_many.assert_called_once_with(self.block, {'content': 'new content'}) self.settings.set_many.assert_called_once_with(self.block, {'settings': 'new settings'}) def test_invalid_scope(self): with pytest.raises(InvalidScopeError): self.split.get(self.block, 'user_state') def test_default(self): self.split.default(self.block, 'content') self.content.default.assert_called_once_with(self.block, 'content') assert not self.settings.default.called