Example #1
0
def _build_value(type_: Type, data: Any, config: Config) -> Any:
    if is_union(type_):
        return _build_value_for_union(union=type_, data=data, config=config)
    elif is_generic_collection(type_) and is_instance(data, extract_origin_collection(type_)):
        return _build_value_for_collection(collection=type_, data=data, config=config)
    elif is_dataclass(type_) and is_instance(data, Data):
        return from_dict(data_class=type_, data=data, config=config)
    return data
Example #2
0
def _build_value_for_collection(collection: Type, data: Any, config: Config) -> Any:
    data_type = data.__class__
    if is_instance(data, Mapping):
        item_type = extract_generic(collection, defaults=(Any, Any))[1]
        return data_type((key, _build_value(type_=item_type, data=value, config=config)) for key, value in data.items())
    elif is_instance(data, tuple):
        types = extract_generic(collection)
        if len(types) == 2 and types[1] == Ellipsis:
            return data_type(_build_value(type_=types[0], data=item, config=config) for item in data)
        return data_type(
            _build_value(type_=type_, data=item, config=config) for item, type_ in zip_longest(data, types)
        )
    item_type = extract_generic(collection, defaults=(Any,))[0]
    return data_type(_build_value(type_=item_type, data=item, config=config) for item in data)
Example #3
0
def _build_value_for_collection(collection: Type, data: Any, config: Config) -> Any:
    if is_instance(data, Mapping):
        return data.__class__(
            (key, _build_value(type_=extract_generic(collection)[1], data=value, config=config))
            for key, value in data.items()
        )
    return data.__class__(_build_value(type_=extract_generic(collection)[0], data=item, config=config) for item in data)
Example #4
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)
Example #5
0
def test_is_instance_with_not_supported_generic_types():
    T = TypeVar("T")

    class X(Generic[T]):
        pass

    assert not is_instance(X[str](), X[str])
Example #6
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)
Example #7
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 value
        except DaciteError:
            pass
    if not config.check_types:
        return data
    raise UnionMatchError(field_type=union, value=data)
Example #8
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()
    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)
 def from_config(
     cls, input_: Union[str, tuple[int, int]]
 ) -> "Prefix":
     if not isinstance(input_, str):
         if not is_instance(
             input_, cast(Type[Any], Tuple[int, int])
         ):
             raise TypeError(
                 f"Expected string or integer pair, got {input_!r}"
             )
         value, bits = input_
         return cls(value, bits)
     for char in input_.lower():
         if char not in "0123456789abcdef":
             raise ValueError(
                 f"Invalid charecter {char!r} in prefix {input_!r}"
             )
     return cls(int(input_, 16), len(input_) * 4)
Example #10
0
def _build_value_for_collection(collection: Type, data: Any,
                                config: Config) -> Any:
    generic = extract_generic(collection)

    if is_instance(data, Mapping):
        return data.__class__(
            (key, _build_value(type_=generic[1], data=value, config=config))
            for key, value in data.items())

    collection_type = extract_origin_collection(collection)
    if collection_type == tuple and not (len(generic) == 2
                                         and generic[1] == Ellipsis):
        return data.__class__(
            _build_value(type_=item_type, data=item, config=config)
            for item, item_type in zip(data, generic))

    return data.__class__(
        _build_value(type_=generic[0], data=item, config=config)
        for item in data)
Example #11
0
def test_is_instance_with_any_type():
    assert is_instance(1, Any)
Example #12
0
def test_is_instance_with_optional_and_not_matching_value_type():
    assert not is_instance(1, Optional[str])
Example #13
0
def test_is_instance_with_nested_generic_collection_and_not_matching_item_type(
):
    assert not is_instance([["test"]], List[List[int]])
Example #14
0
def test_is_instance_with_generic_abstract_collection_and_matching_value_type(
):
    assert is_instance([1], Collection[int])
Example #15
0
def test_is_instance_with_generic_collection_without_specified_inner_types_and_not_matching_value_type(
):
    assert not is_instance([1], Dict)
Example #16
0
def test_is_instance_with_init_var_and_not_matching_value_type():
    assert not is_instance(1, InitVar[str])
Example #17
0
def test_is_instance_with_numeric_tower():
    assert is_instance(1, float)
Example #18
0
def test_is_instance_with_union_and_not_matching_value_type():
    assert not is_instance("test", Union[int, float])
Example #19
0
def test_is_instance_with_generic_mapping_and_not_matching_mapping_key_type():
    assert not is_instance({1: 1}, Dict[str, int])
Example #20
0
def test_is_instance_with_built_in_type_and_matching_value_type():
    assert is_instance(1, int)
Example #21
0
def test_is_instance_with_numeric_tower_and_new_type():
    assert is_instance(1, NewType("NewType", float))
Example #22
0
def test_is_instance_with_numeric_tower_and_optional():
    assert is_instance(1, Optional[float])
Example #23
0
def test_is_instance_with_new_type_and_not_matching_value_type():
    assert not is_instance(1, NewType("MyStr", str))
Example #24
0
def test_is_instance_with_init_var_and_matching_value_type():
    assert is_instance(1, InitVar[int])
Example #25
0
def test_is_instance_with_literal_and_matching_type():
    from typing import Literal

    assert is_instance("A", Literal["A", "B"])
Example #26
0
def test_is_instance_with_generic_mapping_and_not_matching_mapping_value_type(
):
    assert not is_instance({"test": "test"}, Dict[str, int])
Example #27
0
def test_is_instance_with_built_in_type_and_not_matching_value_type():
    assert not is_instance("test", int)
Example #28
0
def test_is_instance_with_optional_literal_and_not_matching_type():
    from typing import Literal

    assert not is_instance("C", Optional[Literal["A", "B"]])
Example #29
0
def test_is_instance_with_generic_collection_and_matching_value_type():
    assert is_instance([1], List[int])
Example #30
0
def test_is_instance_with_optional_literal_and_none():
    from typing import Literal

    assert is_instance(None, Optional[Literal["A", "B"]])