def test_transform_value_with_generic_mapping(): assert transform_value({ str: str, int: int }, [], Dict[str, int], {1: "2"}) == { "1": 2 }
def _build_value_for_union(union: Type, data: Any, config: Config) -> Any: types = extract_generic(union) if is_optional(union) and len(types) == 2: return _build_value(type_=types[0], data=data, config=config) union_matches = {} for inner_type in types: try: # noinspection PyBroadException try: data = transform_value(type_hooks=config.type_hooks, cast=config.cast, target_type=inner_type, value=data) except Exception: # pylint: disable=broad-except continue value = _build_value(type_=inner_type, data=data, config=config) if is_instance(value, inner_type): if config.strict_unions_match: union_matches[inner_type] = value else: return value except DaciteError: pass if config.strict_unions_match: if len(union_matches) > 1: raise StrictUnionMatchError(union_matches) return union_matches.popitem()[1] if not config.check_types: return data raise UnionMatchError(field_type=union, value=data)
def test_transform_value_with_new_type(): MyStr = NewType("MyStr", str) assert transform_value({ MyStr: str.upper, str: str.lower }, [], MyStr, "Test") == "TEST"
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_transform_value_with_nested_generic_mapping(): assert transform_value({ str: str, int: int }, [], Dict[str, Dict[str, int]], {1: { 2: "3" }}) == { "1": { "2": 3 } }
def _build_value_for_union(union: Type, data: Any, config: Config) -> Any: types = extract_generic(union) if is_optional(union) and len(types) == 2: return _build_value(type_=types[0], data=data, config=config) for inner_type in types: try: value = _build_value(type_=inner_type, data=data, config=config) if is_instance(value, inner_type): return transform_value( type_hooks=config.type_hooks, cast=config.cast, target_type=inner_type, value=value ) except DaciteError: pass if not config.check_types: return data raise UnionMatchError(field_type=union, value=data)
def test_transform_value_with_cast_matching_base_class(): class MyInt(int): pass assert transform_value({}, [int], MyInt, "1") == 1
def test_transform_value_without_matching_generic_sequence(): assert transform_value({}, [], List[int], {1}) == {1}
def test_transform_value_with_matching_type(): assert transform_value({int: lambda x: x + 1}, [], int, 1) == 2
def test_transform_value_with_cast_matching_type(): assert transform_value({}, [int], int, "1") == 1
def test_transform_value_with_optional_and_exact_matching_type(): assert transform_value({Optional[str]: str}, [], Optional[str], None) == "None"
def test_transform_value_with_optional_and_none_value(): assert transform_value({str: str}, [], Optional[str], None) is None
def test_transform_value_with_generic_abstract_collection(): assert transform_value({str: str}, [], Collection[str], [1]) == ["1"]
def test_transform_value_without_matching_type(): assert transform_value({}, [], str, 1) == 1
def test_transform_value_with_generic_sequence_and_matching_item(): assert transform_value({str: str}, [], List[str], [1]) == ["1"]
def test_transform_value_with_generic_sequence_and_matching_both_item_and_sequence( ): assert transform_value({ List[int]: lambda x: list(reversed(x)), int: int }, [], List[int], ["1", "2"]) == [2, 1]
def test_transform_value_with_generic_sequence_and_matching_sequence(): assert transform_value({List[int]: lambda x: list(reversed(x))}, [], List[int], [1, 2]) == [2, 1]
def test_transform_value_with_nested_generic_sequence(): assert transform_value({str: str}, [], List[List[str]], [[1]]) == [["1"]]
def test_transform_value_with_optional_and_not_none_value(): assert transform_value({str: str}, Optional[str], 1) == "1"