def test_deep_merge_dicts(self): arg1 = { ('C1', 'CLUSTER'): { ('N1', 'NODE'): { ('NS1', 'NAMESPACE'): { ('CONFIG1', 'KEY'): (1, []) }, ('NS2', 'NAMESPACE'): { ('CONFIG2', 'KEY'): (2, []), ('CONFIG3', 'KEY'): (3, []) } } } } arg2 = { ('C1', 'CLUSTER'): { ('N1', 'NODE'): { ('NS3', 'NAMESPACE'): { ('CONFIG1', 'KEY'): (3, []) }, ('NS2', 'NAMESPACE'): { ('CONFIG2', 'KEY'): (4, []), ('CONFIG5', 'KEY'): (7, []) } } } } expected = { ('C1', 'CLUSTER'): { ('N1', 'NODE'): { ('NS1', 'NAMESPACE'): { ('CONFIG1', 'KEY'): (1, []) }, ('NS3', 'NAMESPACE'): { ('CONFIG1', 'KEY'): (3, []) }, ('NS2', 'NAMESPACE'): { ('CONFIG2', 'KEY'): (2, []), ('CONFIG3', 'KEY'): (3, []), ('CONFIG5', 'KEY'): (7, []) } } } } result = util.deep_merge_dicts(arg1, arg2) self.assertEqual( result, expected, "deep_merge_dicts did not return the expected result")
def do_group_by(data, group_by, keys=[]): if not group_by: raise HealthException("No Group ID for group by operation") if not data: raise HealthException("Wrong Input Data for group by operation.") if not isinstance(data, dict): raise HealthException("Wrong group id %s for group by operation." % (str(group_by))) res = {} for k, t in data.keys(): temp_d = res if t == group_by: if (k, t) not in temp_d: temp_d[(k, t)] = {} if keys: temp_d = temp_d[(k, t)] for _k in keys[:-1]: if _k not in temp_d: temp_d[_k] = {} temp_d = temp_d[_k] temp_d[keys[-1]] = data[(k, t)] else: temp_d[(k, t)] = data[(k, t)] else: keys.append((k, t)) try: res = deep_merge_dicts( res, do_group_by(data[(k, t)], group_by, keys)) except Exception as e: raise e finally: keys.remove((k, t)) return res
def select_keys_from_dict(data={}, keys=[], from_keys=[], ignore_keys=[], save_param=None, config_param=False): """ Function takes dictionary, list of keys to fetch, list of from_keys to filter scope Returns dictionary of selected keys and values """ if not data or not isinstance(data, dict): raise HealthException("Wrong Input Data for select operation.") result_dict = {} if not keys: raise HealthException("No key provided for select operation.") for _key in data: if from_keys: f_key = from_keys[0] if isinstance(_key, tuple): # from_keys work with static component keys only, if we get # tuple keys means we have done with checking of all component # keys and not found any from key match so no need to check # further in this direction break if (f_key == "ALL") or (_key == f_key): # from_key is ALL or matching with _key child_res = select_keys_from_dict( data[_key], keys=keys, from_keys=from_keys[1:] if len(from_keys) > 1 else [], ignore_keys=ignore_keys, save_param=save_param, config_param=config_param) else: # no key match, need to check further child_res = select_keys_from_dict(data[_key], keys=keys, from_keys=from_keys, ignore_keys=ignore_keys, save_param=save_param, config_param=config_param) if child_res: if f_key == "ALL": # It assumes ALL is only for top snapshot level result_dict[(_key, "SNAPSHOT")] = copy.deepcopy(child_res) else: result_dict = deep_merge_dicts(result_dict, copy.deepcopy(child_res)) else: # if (False, "*", None) in keys and isinstance(_key, tuple): # result_dict[_key] = copy.deepcopy(data[_key]) if isinstance(_key, tuple) and _key[1] == "KEY": for check_substring, s_key, new_name in keys: if ((s_key == "*" and not _is_key_in_ignore_keys(_key[0], ignore_keys)) or (check_substring and re.search(s_key, _key[0])) or (not check_substring and _key[0] == s_key)): val_to_save = create_value_list_to_save( save_param=save_param, key=_key[0], value=data[_key], formatting=not config_param) if new_name: result_dict[( new_name, "KEY")] = create_health_internal_tuple( data[_key], val_to_save) else: result_dict[_key] = create_health_internal_tuple( data[_key], val_to_save) break elif data[_key] and isinstance(data[_key], dict): child_res = select_keys_from_dict(data[_key], keys=keys, ignore_keys=ignore_keys, save_param=save_param, config_param=config_param) if child_res: if isinstance(_key, tuple): result_dict[_key] = copy.deepcopy(child_res) else: result_dict = deep_merge_dicts( result_dict, copy.deepcopy(child_res)) return result_dict