"""Utilities to perform various checksMichel BierlaireFri Apr 5 11:09:39 2024"""fromtypingimportAny
[docs]defcheck_consistency_of_named_dicts(named_dicts:dict[str,dict[Any,Any]])->tuple[bool,str|None]:"""Verify that all dictionaries have the same set of keys. If not, report the inconsistencies. :param named_dicts: A dictionary where each key is a name (str) and each value is a dictionary to check. :return: True if keys are consistent across all dictionaries, False otherwise. If not consistent, returns a report detailing the inconsistencies. """# Initialize variablesdict_names=list(named_dicts.keys())keys=[set(d.keys())fordinnamed_dicts.values()]consistent=Trueinconsistencies=[]# Reference keys for comparisonreference_keys=keys[0]reference_name=dict_names[0]# Compare each set of keys with the first to check for consistencyfori,(name,key_set)inenumerate(zip(dict_names[1:],keys[1:]),start=1):ifkey_set!=reference_keys:consistent=Falsemissing_in_ref=reference_keys-key_setextra_in_ref=key_set-reference_keysifmissing_in_ref:inconsistencies.append(f'{name} missing keys compared to {reference_name}: {missing_in_ref}.')ifextra_in_ref:inconsistencies.append(f'{name} has extra keys compared to {reference_name}: {extra_in_ref}.')# Compile the report if there are inconsistenciesreport=Noneifnotconsistent:report="Inconsistencies found among dictionaries:\n"+"\n".join(inconsistencies)returnconsistent,report
[docs]defvalidate_dict_types(parameter:dict,name:str,value_type:type,key_type:type=int)->None:"""Validate the types of keys and values in a dictionary. :param parameter: The dictionary parameter to validate. :param name: The name of the parameter for error messages. :param value_type: The expected type of the dictionary values. :param key_type: The expected type of the dictionary keys. Default is int. :raises TypeError: If key or value types do not match expectations. """ifnotisinstance(parameter,dict):raiseTypeError(f"{name} must be a dict, got {type(parameter).__name__} instead.")forkey,valueinparameter.items():ifnotisinstance(key,key_type):raiseTypeError(f"Keys in {name} must be of type {key_type.__name__}, found type {type(key).__name__}.")ifnot(isinstance(value,value_type)orvalueisNone):raiseTypeError(f"Values in {name} must be of type {value_type.__name__} or None, found type {type(value).__name__}.")