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
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
def test_is_union_with_non_union(): assert not is_union(int)
def test_is_union_with_union(): assert is_union(Union[int, float])
def _name(type_: Type) -> str: return type_.__name__ if hasattr( type_, "__name__") and not is_union(type_) else str(type_)