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 test_create_instance_with_simple_data_class(): @dataclass class X: i: int instance = create_instance(data_class=X, init_values={"i": 1}, post_init_values={}) assert instance == X(i=1)
def test_create_instance_with_post_init_values(): @dataclass class X: i: int j: int = field(init=False) instance = create_instance(data_class=X, init_values={"i": 1}, post_init_values={"j": 2}) assert instance.i == 1 assert instance.j == 2
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() config.validate(data_class, data) try: data_class_hints = get_type_hints(data_class, globalns=config.forward_references) except NameError as error: raise ForwardReferenceError(str(error)) for field in fields(data_class): field = copy.copy(field) field.type = data_class_hints[field.name] try: try: value = _build_value(type_=field.type, data=config.get_value(field, data), config=config.make_inner(field)) 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 ValueNotFoundError: 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)