def is_incompatible(type_: Type[Any]) -> bool: opt = _resolve_optional(type_) # Unions are not supported (Except Optional) if not opt[0] and _is_union(type_): return True type_ = opt[1] if type_ in (type(None), tuple, list, dict): return False try: if is_list_annotation(type_): lt = get_list_element_type(type_) return is_incompatible(lt) if is_dict_annotation(type_): kvt = get_dict_key_value_types(type_) if not issubclass(kvt[0], (str, Enum)): return True return is_incompatible(kvt[1]) if is_tuple_annotation(type_): for arg in type_.__args__: if arg is not ... and is_incompatible(arg): return True return False if get_origin(type_) is Callable: args = get_args(type_) for arg in args[0]: if arg is not ... and is_incompatible(arg): return True if is_incompatible(args[1]): return True return False except ValidationError: return True if type_ is Any or issubclass(type_, (int, float, str, bool, Enum)): return False if is_structured_config(type_): try: OmegaConf.structured(type_) # verify it's actually legal except ValidationError as e: log.debug( f"Failed to create DictConfig from ({type_.__name__}) : {e}, flagging as incompatible" ) return True return False return True
def generate(cfg: ConfigenConf, module_name: str, class_name: str) -> str: full_name = f"{module_name}.{class_name}" cls = hydra.utils.get_class(full_name) sig = inspect.signature(cls) template = jinja_env.get_template("dataclass.j2") params: List[Parameter] = [] for name, p in sig.parameters.items(): type_ = p.annotation if type_ == sig.empty or _is_union(type_): type_ = Any params.append( Parameter( name=name, type_str=type_str(type_), default=p.default, passthrough=_is_passthrough(type_), )) return template.render(target=f'"{full_name}"', class_name=class_name, params=params, header=cfg.header)