Source code for squadds.database.contributor_validation

"""Pure helpers for contributor content comparison and reporting."""

from __future__ import annotations


[docs] def get_nested_value(dictionary, keys): """Walk a dotted path through a nested dictionary and return `None` on missing keys.""" for key in keys.split("."): if dictionary is not None and key in dictionary: dictionary = dictionary[key] else: return None return dictionary
[docs] def find_common_key_type_matches(dict1, dict2, path=""): """Yield dotted-key comparisons for matching and missing nested paths.""" common_keys = set(dict1.keys()) & set(dict2.keys()) diff_keys = (set(dict1.keys()) - set(dict2.keys())) | (set(dict2.keys()) - set(dict1.keys())) for key in common_keys: new_path = f"{path}.{key}" if path else key if isinstance(dict1[key], dict) and isinstance(dict2[key], dict): yield from find_common_key_type_matches(dict1[key], dict2[key], new_path) else: if type(dict1[key]) != type(dict2[key]): yield new_path, False else: yield new_path, True for key in diff_keys: new_path = f"{path}.{key}" if path else key yield new_path, None
[docs] def summarize_content_differences(data: dict, ref: dict): """Return categorized dotted-key differences between contributor data and a reference entry.""" result = list(find_common_key_type_matches(data, ref)) mismatched_keys = [key for key, match in result if match is False] missing_keys = [key for key, match in result if match is None] return mismatched_keys, missing_keys