def get_environ2(): """Returns currently defined course settings as a dictionary.""" gDefier_yaml = None gDefier_yaml_dict = None ns = ApplicationContext.get_namespace_name_for_request() app_context = sites.get_app_context_for_namespace(ns) course_data_filename = sites.abspath(app_context.get_home_folder(), DFR_CONFIG_FILENAME) if app_context.fs.isfile(course_data_filename): gDefier_yaml = app_context.fs.open(course_data_filename) if not gDefier_yaml: return deep_dict_merge(gDefier_model.DEFAULT_COURSE_GDEFIER_DICT, []) try: gDefier_yaml_dict = yaml.safe_load( gDefier_yaml.read().decode('utf-8')) except Exception as e: # pylint: disable-msg=broad-except logging.info( 'Error: gDefier.yaml file at %s not accessible, ' 'loading defaults. %s', course_data_filename, e) if not gDefier_yaml_dict: return deep_dict_merge(gDefier_model.DEFAULT_COURSE_GDEFIER_DICT, []) return deep_dict_merge( gDefier_yaml_dict, gDefier_model.DEFAULT_COURSE_GDEFIER_DICT)
def test_dict_merge(self): real_values = {'foo': 'bar', 'baz': {'alice': 'john'}} real_original = dict(real_values.items()) default_values = {'foo': 'baz', 'baz': {'alice': 'ana', 'bob': 'sue'}} default_original = dict(default_values.items()) # Check merge. assert {'foo': 'bar', 'baz': {'bob': 'sue', 'alice': 'john'}} == ( courses.deep_dict_merge(real_values, default_values)) # Check originals dicts are intact. assert real_original == real_values assert default_original == default_values # Check merge into an empty dict. assert courses.DEFAULT_COURSE_YAML_DICT == courses.deep_dict_merge( {}, courses.DEFAULT_COURSE_YAML_DICT) # Check value does not merge into dictionary. real_values = {'foo': 'bar'} default_values = {'foo': {'bar': 'baz'}} assert {'foo': 'bar'} == ( courses.deep_dict_merge(real_values, default_values)) # Test array element. real_values = {'foo': [1, 2, 3]} default_values = {'baz': [4, 5, 6]} assert {'foo': [1, 2, 3], 'baz': [4, 5, 6]} == ( courses.deep_dict_merge(real_values, default_values))
def update_course_config(name, settings): """Merge settings into the saved course.yaml configuration. Args: name: Name of the course. E.g., 'my_test_course'. settings: A nested dict of name/value settings. Names for items here can be found in modules/dashboard/course_settings.py in create_course_registry. See below in simple_add_course() for an example. Returns: Context object for the modified course. """ site_type = 'course' namespace = 'ns_%s' % name slug = '/%s' % name rule = '%s:%s::%s' % (site_type, slug, namespace) context = sites.get_all_courses(rule)[0] environ = courses.deep_dict_merge(settings, courses.Course.get_environ(context)) course = courses.Course(handler=None, app_context=context) course.save_settings(environ) course_config = config.Registry.test_overrides.get( sites.GCB_COURSES_CONFIG.name, 'course:/:/') if rule not in course_config: course_config = '%s, %s' % (rule, course_config) sites.setup_courses(course_config) return context
def put(self): """Handles REST PUT verb with JSON payload.""" assert self.app_context.is_editable_fs() request_param = self.request.get('request') if not request_param: transforms.send_json_response( self, 400, 'Missing "request" parameter.') return try: request = transforms.loads(request_param) except ValueError: transforms.send_json_response( self, 400, 'Malformed "request" parameter.') return key = request.get('key') if not key: transforms.send_json_response( self, 400, 'Request missing "key" parameter.') return payload_param = request.get('payload') if not payload_param: transforms.send_json_response( self, 400, 'Request missing "payload" parameter.') return try: payload = transforms.loads(payload_param) except ValueError: transforms.send_json_response( self, 400, 'Malformed "payload" parameter.') return if not self.assert_xsrf_token_or_fail( request, self.XSRF_ACTION, {'key': key}): return if not permissions.can_edit(self.app_context, constants.SCOPE_COURSE_SETTINGS): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return request_data = self.process_put(request, payload) schema = self.get_course().create_settings_schema() permissions.SchemaPermissionRegistry.redact_schema_to_permitted_fields( self.app_context, constants.SCOPE_COURSE_SETTINGS, schema) schema.redact_entity_to_schema(payload) if request_data: course_settings = courses.deep_dict_merge( request_data, self.get_course_dict()) self.postprocess_put(course_settings, request) if not self.get_course().save_settings(course_settings): transforms.send_json_response(self, 412, 'Validation error.') transforms.send_json_response(self, 200, 'Saved.')
def put(self): """Handles REST PUT verb with JSON payload.""" assert is_editable_fs(self.app_context) request = transforms.loads(self.request.get('request')) key = request.get('key') if not self.assert_xsrf_token_or_fail( request, 'basic-course-settings-put', {'key': key}): return if not CourseSettingsRights.can_edit(self): transforms.send_json_response(self, 401, 'Access denied.', {'key': key}) return payload = request.get('payload') request_data = {} CourseSettingsRESTHandler.REGISTORY.convert_json_to_entity( transforms.loads(payload), request_data) course_data = request_data['course'] if 'forum_email' in course_data.keys(): forum_email = course_data['forum_email'] forum_web_url = self.get_groups_web_url(forum_email) if forum_web_url: course_data['forum_url'] = forum_web_url forum_web_url = self.get_groups_embed_url(forum_email) if forum_web_url: course_data['forum_embed_url'] = forum_web_url if 'announcement_list_email' in course_data.keys(): announcement_email = course_data['announcement_list_email'] announcement_web_url = self.get_groups_web_url(announcement_email) if announcement_web_url: course_data['announcement_list_url'] = announcement_web_url entity = courses.deep_dict_merge(request_data, self.get_course_dict()) content = yaml.safe_dump(entity) try: self.validate_content(content) content_stream = vfs.string_to_stream(unicode(content)) except Exception as e: # pylint: disable=W0703 transforms.send_json_response(self, 412, 'Validation error: %s' % e) return # Store new file content. fs = self.app_context.fs.impl filename = fs.physical_to_logical(key) fs.put(filename, content_stream) # Send reply. transforms.send_json_response(self, 200, 'Saved.')
def put(self): """Handles REST PUT verb with JSON payload.""" assert is_editable_fs(self.app_context) request = transforms.loads(self.request.get('request')) key = request.get('key') if not self.assert_xsrf_token_or_fail( request, 'basic-course-settings-put', {'key': key}): return if not CourseSettingsRights.can_edit(self): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return payload = request.get('payload') request_data = {} CourseSettingsRESTHandler.REGISTORY.convert_json_to_entity( transforms.loads(payload), request_data) course_data = request_data['course'] if 'forum_email' in course_data.keys(): forum_email = course_data['forum_email'] forum_web_url = self.get_groups_web_url(forum_email) if forum_web_url: course_data['forum_url'] = forum_web_url forum_web_url = self.get_groups_embed_url(forum_email) if forum_web_url: course_data['forum_embed_url'] = forum_web_url if 'announcement_list_email' in course_data.keys(): announcement_email = course_data['announcement_list_email'] announcement_web_url = self.get_groups_web_url(announcement_email) if announcement_web_url: course_data['announcement_list_url'] = announcement_web_url entity = courses.deep_dict_merge(request_data, self.get_course_dict()) content = yaml.safe_dump(entity) try: self.validate_content(content) content_stream = vfs.string_to_stream(unicode(content)) except Exception as e: # pylint: disable=W0703 transforms.send_json_response(self, 412, 'Validation error: %s' % e) return # Store new file content. fs = self.app_context.fs.impl filename = fs.physical_to_logical(key) fs.put(filename, content_stream) # Send reply. transforms.send_json_response(self, 200, 'Saved.')
def put(self): """Handles REST PUT verb with JSON payload.""" assert self.app_context.is_editable_fs() request_param = self.request.get('request') if not request_param: transforms.send_json_response(self, 400, 'Missing "request" parameter.') return try: request = transforms.loads(request_param) except ValueError: transforms.send_json_response(self, 400, 'Malformed "request" parameter.') return key = request.get('key') if not key: transforms.send_json_response(self, 400, 'Request missing "key" parameter.') return payload_param = request.get('payload') if not payload_param: transforms.send_json_response( self, 400, 'Request missing "payload" parameter.') return try: payload = transforms.loads(payload_param) except ValueError: transforms.send_json_response(self, 400, 'Malformed "payload" parameter.') return if not self.assert_xsrf_token_or_fail(request, self.XSRF_ACTION, {'key': key}): return if not CourseSettingsRights.can_edit(self): transforms.send_json_response(self, 401, 'Access denied.', {'key': key}) return request_data = self.process_put(request, payload) if request_data: course_settings = courses.deep_dict_merge(request_data, self.get_course_dict()) self.postprocess_put(course_settings, request) if not self.get_course().save_settings(course_settings): transforms.send_json_response(self, 412, 'Validation error.') transforms.send_json_response(self, 200, 'Saved.')
def put(self): """Handles REST PUT verb with JSON payload.""" assert self.app_context.is_editable_fs() request_param = self.request.get('request') if not request_param: transforms.send_json_response( self, 400, 'Missing "request" parameter.') return try: request = transforms.loads(request_param) except ValueError: transforms.send_json_response( self, 400, 'Malformed "request" parameter.') return key = request.get('key') if not key: transforms.send_json_response( self, 400, 'Request missing "key" parameter.') return payload_param = request.get('payload') if not payload_param: transforms.send_json_response( self, 400, 'Request missing "payload" parameter.') return try: payload = transforms.loads(payload_param) except ValueError: transforms.send_json_response( self, 400, 'Malformed "payload" parameter.') return if not self.assert_xsrf_token_or_fail( request, self.XSRF_ACTION, {'key': key}): return if not CourseSettingsRights.can_edit(self): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return request_data = self.process_put(request, payload) if request_data: course_settings = courses.deep_dict_merge( request_data, self.get_course_dict()) self.postprocess_put(course_settings, request) if not self.get_course().save_settings(course_settings): transforms.send_json_response(self, 412, 'Validation error.') transforms.send_json_response(self, 200, 'Saved.')
def test_recursive_merge(self): tgt = {'a': {'b': 1}} src = {'a': 1, 'c': {'d': 4}} r = courses.deep_dict_merge(tgt, src) e = {'a': {'b': 1}, 'c': {'d': 4}} self.assertEqual(e, r)
def test_non_recursive_merge(self): tgt = {'a': 1, 'b': 2, 'd': 4} src = {'a': 1, 'b': 22, 'c': 3} r = courses.deep_dict_merge(tgt, src) e = {'a': 1, 'b': 2, 'c': 3, 'd': 4} self.assertEqual(e, r)
def test_tgt_empty_merge(self): tgt = {} src = {'a': 1} r = courses.deep_dict_merge(tgt, src) self.assertEqual(src, r)
def test_src_empty_merge(self): tgt = {'a': {'b': 2}, 'c': None} src = {} r = courses.deep_dict_merge(tgt, src) self.assertEqual(tgt, r)
def test_both_empty_merge(self): tgt = {} src = {} r = courses.deep_dict_merge(tgt, src) self.assertEqual({}, r)
def _get_environ(self, app_context): return courses.deep_dict_merge( self._new_env, self._old_get_environ(app_context))