def get(self, key): # simplest case, field is directly set if key.field_name in self._fields: return self._fields[key.field_name] # parent undefined in editing runtime (I think) if key.scope == Scope.parent: # see STUD-624. Right now copies MongoKeyValueStore.get's behavior of returning None return None if key.scope == Scope.children: # didn't find children in _fields; so, see if there's a default raise KeyError() elif key.scope == Scope.settings: # didn't find in _fields; so, get from inheritance since not locally set if key.field_name in self._inherited_settings: return self._inherited_settings[key.field_name] else: # or get default raise KeyError() elif key.scope == Scope.content: if key.field_name == 'location': return self._location elif key.field_name == 'category': return self._category elif isinstance(self._definition, DefinitionLazyLoader): self._load_definition() if key.field_name in self._fields: return self._fields[key.field_name] raise KeyError() else: raise InvalidScopeError(key.scope)
def set(self, key, value): if key.scope == Scope.children: self._children = value elif key.scope == Scope.settings: self._metadata[key.field_name] = value elif key.scope == Scope.content: if key.field_name == 'data' and not isinstance(self._data, dict): self._data = value else: self._data[key.field_name] = value else: raise InvalidScopeError(key.scope)
def delete(self, key): if key.scope == Scope.children: self._children = [] elif key.scope == Scope.settings: if key.field_name in self._metadata: del self._metadata[key.field_name] elif key.scope == Scope.content: if key.field_name == 'data' and not isinstance(self._data, dict): self._data = None else: del self._data[key.field_name] else: raise InvalidScopeError(key.scope)
def set_many(self, kv_dict): """ Provide a bulk save mechanism. `kv_dict`: A dictionary of dirty fields that maps xblock.DbModel._key : value """ saved_fields = [] # field_objects maps a field_object to a list of associated fields field_objects = dict() for field in kv_dict: # Check field for validity if field.field_name in self._descriptor_model_data: raise InvalidWriteError( "Not allowed to overwrite descriptor model data", field.field_name) if field.scope not in self._allowed_scopes: raise InvalidScopeError(field.scope) # If the field is valid and isn't already in the dictionary, add it. field_object = self._model_data_cache.find_or_create(field) if field_object not in field_objects.keys(): field_objects[field_object] = [] # Update the list of associated fields field_objects[field_object].append(field) # Special case when scope is for the user state, because this scope saves fields in a single row if field.scope == Scope.user_state: state = json.loads(field_object.state) state[field.field_name] = kv_dict[field] field_object.state = json.dumps(state) else: # The remaining scopes save fields on different rows, so # we don't have to worry about conflicts field_object.value = json.dumps(kv_dict[field]) for field_object in field_objects: try: # Save the field object that we made above field_object.save() # If save is successful on this scope, add the saved fields to # the list of successful saves saved_fields.extend([ field.field_name for field in field_objects[field_object] ]) except DatabaseError: log.error('Error saving fields %r', field_objects[field_object]) raise KeyValueMultiSaveError(saved_fields)
def get(self, key): if key.scope == Scope.children: return self._children elif key.scope == Scope.parent: return None elif key.scope == Scope.settings: return self._metadata[key.field_name] elif key.scope == Scope.content: if key.field_name == 'data' and not isinstance(self._data, dict): return self._data else: return self._data[key.field_name] else: raise InvalidScopeError(key.scope)
def delete(self, key): # handle any special cases if key.scope not in [Scope.children, Scope.settings, Scope.content]: raise InvalidScopeError(key.scope) if key.scope == Scope.content: if key.field_name == 'location': return # noop elif key.field_name == 'category': # TODO should this raise an exception? category is not deleteable. return # noop else: self._load_definition() # delete the field value if key.field_name in self._fields: del self._fields[key.field_name]
def set(self, key, value): # handle any special cases if key.scope not in [Scope.children, Scope.settings, Scope.content]: raise InvalidScopeError(key.scope) if key.scope == Scope.content: if key.field_name == 'location': self._location = value # is changing this legal? return elif key.field_name == 'category': # TODO should this raise an exception? category is not changeable. return else: self._load_definition() # set the field self._fields[key.field_name] = value
def _retrieve_fields(self, scope, fields): """ Queries the database for all of the fields in the specified scope """ if scope in (Scope.children, Scope.parent): return [] elif scope == Scope.user_state: return self._chunked_query( StudentModule, 'module_state_key__in', (descriptor.location.url() for descriptor in self.descriptors), course_id=self.course_id, student=self.user.pk, ) elif scope == Scope.content: return self._chunked_query( XModuleContentField, 'definition_id__in', (descriptor.location.url() for descriptor in self.descriptors), field_name__in=set(field.name for field in fields), ) elif scope == Scope.settings: return self._chunked_query( XModuleSettingsField, 'usage_id__in', ( '%s-%s' % (self.course_id, descriptor.location.url()) for descriptor in self.descriptors ), field_name__in=set(field.name for field in fields), ) elif scope == Scope.preferences: return self._chunked_query( XModuleStudentPrefsField, 'module_type__in', set(descriptor.module_class.__name__ for descriptor in self.descriptors), student=self.user.pk, field_name__in=set(field.name for field in fields), ) elif scope == Scope.user_info: return self._query( XModuleStudentInfoField, student=self.user.pk, field_name__in=set(field.name for field in fields), ) else: raise InvalidScopeError(scope)
def set(self, key, value): if key.field_name in self._descriptor_model_data: raise InvalidWriteError("Not allowed to overwrite descriptor model data", key.field_name) field_object = self._model_data_cache.find_or_create(key) if key.scope not in self._allowed_scopes: raise InvalidScopeError(key.scope) if key.scope == Scope.user_state: state = json.loads(field_object.state) state[key.field_name] = value field_object.state = json.dumps(state) else: field_object.value = json.dumps(value) field_object.save()
def has(self, key): if key.field_name in self._descriptor_model_data: return key.field_name in self._descriptor_model_data if key.scope == Scope.parent: return True if key.scope not in self._allowed_scopes: raise InvalidScopeError(key.scope) field_object = self._model_data_cache.find(key) if field_object is None: return False if key.scope == Scope.user_state: return key.field_name in json.loads(field_object.state) else: return True
def delete(self, key): if key.field_name in self._descriptor_model_data: raise InvalidWriteError("Not allowed to deleted descriptor model data", key.field_name) if key.scope not in self._allowed_scopes: raise InvalidScopeError(key.scope) field_object = self._model_data_cache.find(key) if field_object is None: raise KeyError(key.field_name) if key.scope == Scope.user_state: state = json.loads(field_object.state) del state[key.field_name] field_object.state = json.dumps(state) field_object.save() else: field_object.delete()
def get(self, key): if key.field_name in self._descriptor_model_data: return self._descriptor_model_data[key.field_name] if key.scope == Scope.parent: return None if key.scope not in self._allowed_scopes: raise InvalidScopeError(key.scope) field_object = self._model_data_cache.find(key) if field_object is None: raise KeyError(key.field_name) if key.scope == Scope.user_state: return json.loads(field_object.state)[key.field_name] else: return json.loads(field_object.value)