def instantiate(config: Union[DictConfig, dict], *args, **kwargs) -> Any: r""" Recursively instantiates classes in a Hydra configuration. Args: config (omegaconf.DictConfig or dict): The config to recursively instantiate from. """ # NOTE this method is really ugly, but it's coming in Hydra 1.1 so no reason # to rewrite it if isinstance(config, dict): config = DictConfig(config) elif isinstance(config, list): config = ListConfig(config) # type: ignore # deepcopy so we can modify config config = deepcopy(config) if isinstance(config, DictConfig): OmegaConf.set_struct(config, False) if "params" in config.keys(): if isinstance(config.get("params"), (dict, DictConfig)): params = dict(config.get("params")) # type: ignore elif isinstance(config.get("params"), (list, ListConfig)): params = list(config.get("params")) # type: ignore else: params = {} def is_subclass(d): if isinstance(d, (dict, DictConfig)): return _has_instantiate_key(d.keys()) elif isinstance(d, (list, ListConfig)): return any([_has_instantiate_key(x.keys()) for x in d if isinstance(x, (dict, DictConfig))]) return False if isinstance(params, list): # type: ignore for i, subconfig in enumerate(params): subconfig = DictConfig(subconfig) if isinstance(subconfig, (dict, DictConfig)) and "params" not in subconfig.keys(): subconfig["params"] = {} subconfig._set_parent(config) # type: ignore params[i] = HydraMixin.instantiate(subconfig) del config["params"] return instantiate(config, *params, *args, **kwargs) else: subclasses = {key: subconfig for key, subconfig in params.items() if is_subclass(subconfig)} # type: ignore # instantiate recursively, remove those keys from config used in hydra instantiate call for key, subconfig in subclasses.items(): if isinstance(subconfig, (dict, DictConfig)): subconfig = DictConfig(subconfig) # avoid issues when cls given without params if "params" not in subconfig: subconfig["params"] = {} subconfig._set_parent(config) # type: ignore subclasses[key] = HydraMixin.instantiate(subconfig) else: subclasses[key] = [HydraMixin.instantiate(x) for x in subconfig] del config.get("params")[key] subclasses.update(kwargs) return instantiate(config, *args, **subclasses)