def from_dict(data_class: Type[T], data: Data, config: Optional[Config] = None) -> T: """Create a data class instance from a dictionary. :param data_class: a data class type :param data: a dictionary of a input data :param config: a configuration of the creation process :return: an instance of a data class """ init_values: Data = {} post_init_values: Data = {} config = config or Config() try: data_class_hints = get_type_hints(data_class, globalns=config.forward_references) except NameError as error: raise ForwardReferenceError(str(error)) data_class_fields = get_fields(data_class) if config.strict: extra_fields = set(data.keys()) - {f.name for f in data_class_fields} if extra_fields: raise UnexpectedDataError(keys=extra_fields) for field in data_class_fields: field = copy.copy(field) field.type = data_class_hints[field.name] try: try: field_data = data[field.name] transformed_value = transform_value( type_hooks=config.type_hooks, cast=config.cast, target_type=field.type, value=field_data) value = _build_value(type_=field.type, data=transformed_value, config=config) except DaciteFieldError as error: error.update_path(field.name) raise if config.check_types and not is_instance(value, field.type): raise WrongTypeError(field_path=field.name, field_type=field.type, value=value) except KeyError: try: value = get_default_value_for_field(field) except DefaultValueNotFoundError: if not field.init: continue raise MissingValueError(field.name) if field.init: init_values[field.name] = value else: post_init_values[field.name] = value return create_instance(data_class=data_class, init_values=init_values, post_init_values=post_init_values)
def _validate_data_key(self, data_class: Type, data: Data, parameter: str, validator=lambda v, c: v in c) -> None: input_data_keys = set(data.keys()) data_class_fields = {field.name: field for field in fields(data_class)} for field_name, input_data_field in getattr(self, parameter).items(): if "." not in field_name: field = data_class_fields[field_name] if not validator(input_data_field, input_data_keys ) and not has_field_default_value(field): raise InvalidConfigurationError( parameter=parameter, available_choices=input_data_keys, value=input_data_field)