Ejemplo n.º 1
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)
Ejemplo n.º 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)
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
def _build_value_for_union(union: Type, data: Any, config: Config) -> Any:
    types = [
        type_ for type_ in extract_generic(union) if type_ is not type(None)
    ]
    if is_optional(union) and len(extract_generic(union)) == 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)
Ejemplo n.º 5
0
    def load_from_template(template, cfg_value):
        if isinstance(cfg_value, dict):
            cfg_obj = SimpleNamespace()
            for key, value in cfg_value.items():
                nest_template = getattr(template, key, None)
                if nest_template is not None:
                    # it is a nested class which means subsection of config
                    result = load_from_template(nest_template, value)
                    setattr(cfg_obj, key, result)
                else:
                    # it should be either raw type or a Union
                    anno = template.__annotations__[key]
                    if typing_utils.is_union(anno):
                        nest_templates = typing_utils.extract_generic(anno)
                        result = load_from_matching_template(
                            nest_templates, value)
                        setattr(cfg_obj, key, result)
                    else:
                        setattr(cfg_obj, key, value)
            return cfg_obj
        elif isinstance(cfg_value, list):
            if typing_utils.is_generic_collection(template):
                item_template = typing_utils.extract_generic(template)[0]
                if typing_utils.is_union(item_template):
                    item_templates = typing_utils.extract_generic(
                        item_template)
                else:
                    item_templates = [item_template]
                return [
                    load_from_matching_template(item_templates, item)
                    for item in cfg_value
                ]
            else:
                return cfg_value

        else:
            return cfg_value
Ejemplo n.º 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)
Ejemplo n.º 7
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)
Ejemplo n.º 8
0
def test_extract_generic():
    assert extract_generic(List[int]) == (int,)
Ejemplo n.º 9
0
def test_extract_generic_with_defaults():
    assert extract_generic(List, defaults=(Any, )) == (Any, )