Пример #1
0
def test_transform_value_with_generic_mapping():
    assert transform_value({
        str: str,
        int: int
    }, [], Dict[str, int], {1: "2"}) == {
        "1": 2
    }
Пример #2
0
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)
Пример #3
0
def test_transform_value_with_new_type():
    MyStr = NewType("MyStr", str)

    assert transform_value({
        MyStr: str.upper,
        str: str.lower
    }, [], MyStr, "Test") == "TEST"
Пример #4
0
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)
Пример #5
0
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
        }
    }
Пример #6
0
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)
Пример #7
0
def test_transform_value_with_cast_matching_base_class():
    class MyInt(int):
        pass

    assert transform_value({}, [int], MyInt, "1") == 1
Пример #8
0
def test_transform_value_without_matching_generic_sequence():
    assert transform_value({}, [], List[int], {1}) == {1}
Пример #9
0
def test_transform_value_with_matching_type():
    assert transform_value({int: lambda x: x + 1}, [], int, 1) == 2
Пример #10
0
def test_transform_value_with_cast_matching_type():
    assert transform_value({}, [int], int, "1") == 1
Пример #11
0
def test_transform_value_with_optional_and_exact_matching_type():
    assert transform_value({Optional[str]: str}, [], Optional[str],
                           None) == "None"
Пример #12
0
def test_transform_value_with_optional_and_none_value():
    assert transform_value({str: str}, [], Optional[str], None) is None
Пример #13
0
def test_transform_value_with_generic_abstract_collection():
    assert transform_value({str: str}, [], Collection[str], [1]) == ["1"]
Пример #14
0
def test_transform_value_without_matching_type():
    assert transform_value({}, [], str, 1) == 1
Пример #15
0
def test_transform_value_with_generic_sequence_and_matching_item():
    assert transform_value({str: str}, [], List[str], [1]) == ["1"]
Пример #16
0
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]
Пример #17
0
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]
Пример #18
0
def test_transform_value_with_nested_generic_sequence():
    assert transform_value({str: str}, [], List[List[str]], [[1]]) == [["1"]]
Пример #19
0
def test_transform_value_with_optional_and_not_none_value():
    assert transform_value({str: str}, Optional[str], 1) == "1"