def get_config_context(self): """ Return the rendered configuration context for a device or VM. """ if not hasattr(self, "config_context_data"): # Annotation not available, so fall back to manually querying for the config context config_context_data = ConfigContext.objects.get_for_object( self).values_list("data", flat=True) else: config_context_data = self.config_context_data or [] # Annotation has keys "weight" and "name" (used for ordering) and "data" (the actual config context data) config_context_data = [ c["data"] for c in sorted(config_context_data, key=lambda k: (k["weight"], k["name"])) ] # Compile all config data, overwriting lower-weight values with higher-weight values where a collision occurs data = OrderedDict() for context in config_context_data: data = deepmerge(data, context) # If the object has local config context data defined, merge it last if self.local_context_data: data = deepmerge(data, self.local_context_data) return data
def test_patch(self): """ Set user config via PATCH requests. """ url = reverse("users-api:userconfig-list") data = { "a": { "a1": "X", "a2": "Y", }, "b": { "b1": "Z", }, } response = self.client.patch(url, data=data, format="json", **self.header) self.assertDictEqual(response.data, data) self.user.refresh_from_db() self.assertDictEqual(self.user.config_data, data) update_data = {"c": 123} response = self.client.patch(url, data=update_data, format="json", **self.header) new_data = deepmerge(data, update_data) self.assertDictEqual(response.data, new_data) self.user.refresh_from_db() self.assertDictEqual(self.user.config_data, new_data)
def get_config_context(self): """ Return the rendered configuration context for a device or VM. """ # always manually query for config contexts config_context_data = ConfigContext.objects.get_for_object(self).values_list("data", flat=True) # Compile all config data, overwriting lower-weight values with higher-weight values where a collision occurs data = OrderedDict() for context in config_context_data: data = deepmerge(data, context) # If the object has local config context data defined, merge it last if self.local_context_data: data = deepmerge(data, self.local_context_data) return data
def patch(self, request): """ Update the config_data for the currently authenticated User. """ # TODO: How can we validate this data? user = request.user user.config_data = deepmerge(user.config_data, request.data) user.save() return Response(user.config_data)
def patch(self, request): """ Update the UserConfig for the currently authenticated User. """ # TODO: How can we validate this data? userconfig = self.get_queryset().first() userconfig.data = deepmerge(userconfig.data, request.data) userconfig.save() return Response(userconfig.data)
def get_config_context(self): """ Return the rendered configuration context for a device or VM. """ # Compile all config data, overwriting lower-weight values with higher-weight values where a collision occurs data = OrderedDict() if not hasattr(self, "config_context_data"): # The annotation is not available, so we fall back to manually querying for the config context objects config_context_data = ConfigContext.objects.get_for_object( self, aggregate_data=True) else: # The attribute may exist, but the annotated value could be None if there is no config context data config_context_data = self.config_context_data or [] for context in config_context_data: data = deepmerge(data, context) # If the object has local config context data defined, merge it last if self.local_context_data: data = deepmerge(data, self.local_context_data) return data
def test_deepmerge(self): dict1 = { "active": True, "foo": 123, "fruits": { "orange": 1, "apple": 2, "pear": 3, }, "vegetables": None, "dairy": { "milk": 1, "cheese": 2, }, "deepnesting": { "foo": { "a": 10, "b": 20, "c": 30, }, }, } dict2 = { "active": False, "bar": 456, "fruits": { "banana": 4, "grape": 5, }, "vegetables": { "celery": 1, "carrots": 2, "corn": 3, }, "dairy": None, "deepnesting": { "foo": { "a": 100, "d": 40, }, }, } merged = { "active": False, "foo": 123, "bar": 456, "fruits": { "orange": 1, "apple": 2, "pear": 3, "banana": 4, "grape": 5, }, "vegetables": { "celery": 1, "carrots": 2, "corn": 3, }, "dairy": None, "deepnesting": { "foo": { "a": 100, "b": 20, "c": 30, "d": 40, }, }, } self.assertEqual(deepmerge(dict1, dict2), merged)