def set_state(state: Any) -> None: Singleton._instances = state["instances"] # Reinitialize the the Plugin singleton (discover all plugins etc). from hydra.core.plugins import Plugins Plugins.instance() BaseContainer._resolvers = deepcopy(state["omegaconf_resolvers"])
def test_config_repository_exists(self, hydra_restore_singletons: Any, path: str) -> None: Plugins.instance() # initializes config_search_path = create_config_search_path(path) repo = ConfigRepository(config_search_path=config_search_path) assert repo.config_exists("dataset/imagenet.yaml") assert not repo.config_exists("not_found.yaml")
def test_setup_plugins( monkeypatch: Any, plugin: Union[Launcher, Sweeper], config: DictConfig ) -> None: task_function = Mock(spec=TaskFunction) config_loader = ConfigLoaderImpl(config_search_path=create_config_search_path(None)) hydra_context = HydraContext(config_loader=config_loader, callbacks=Callbacks()) plugin_instance = Plugins.instance() monkeypatch.setattr(Plugins, "check_usage", lambda _: None) monkeypatch.setattr(plugin_instance, "_instantiate", lambda _: plugin) msg = dedent( """ Plugin's setup() signature has changed in Hydra 1.1. Support for the old style will be removed in Hydra 1.2. For more info, check https://github.com/facebookresearch/hydra/pull/1581.""" ) with warns(expected_warning=UserWarning, match=re.escape(msg)): if isinstance(plugin, Launcher): Plugins.instance().instantiate_launcher( task_function=task_function, config=config, config_loader=config_loader, hydra_context=hydra_context, ) else: Plugins.instance().instantiate_sweeper( hydra_context=hydra_context, task_function=task_function, config=config, )
def _print_plugins(self) -> None: assert log is not None self._log_header(header="Installed Hydra Plugins", filler="*") all_plugins = {p.__name__ for p in Plugins.instance().discover()} for plugin_type in [ ConfigSource, CompletionPlugin, Launcher, Sweeper, SearchPathPlugin, ]: # Mypy false positive? plugins = Plugins.instance().discover(plugin_type) # type: ignore if len(plugins) > 0: Hydra._log_header(header=f"{plugin_type.__name__}:", prefix="\t") for plugin in plugins: log.debug("\t\t{}".format(plugin.__name__)) if plugin.__name__ in all_plugins: all_plugins.remove(plugin.__name__) if len(all_plugins) > 0: Hydra._log_header(header="Generic plugins: ", prefix="\t") for plugin_name in all_plugins: log.debug("\t\t{}".format(plugin_name))
def test_config_repository_load(self, hydra_restore_singletons: Any, path: str) -> None: Plugins.instance() # initializes config_search_path = create_config_search_path(path) repo = ConfigRepository(config_search_path=config_search_path) ret = repo.load_config(config_path="dataset/imagenet.yaml") assert ret is not None assert ret.config == {"name": "imagenet", "path": "/datasets/imagenet"} assert repo.load_config(config_path="not_found.yaml") is None
def test_register_plugin() -> None: class MyPlugin(SearchPathPlugin): def manipulate_search_path(self, search_path: ConfigSearchPath) -> None: ... Plugins.instance().register(MyPlugin) assert MyPlugin in Plugins.instance().discover(Plugin) assert MyPlugin in Plugins.instance().discover(SearchPathPlugin) assert MyPlugin not in Plugins.instance().discover(Launcher)
def test_config_repository_list( self, hydra_restore_singletons: Any, path: str, config_path: str, expected: List[InputDefault], ) -> None: Plugins.instance() config_search_path = create_config_search_path(path) repo = ConfigRepository(config_search_path=config_search_path) ret = repo.load_config(config_path) assert ret is not None assert ret.defaults_list == expected
def test_config_repository_list( self, hydra_restore_singletons: Any, path: str, config_path: str, results_filter: Optional[ObjectType], expected: List[str], ) -> None: Plugins.instance() # initializes config_search_path = create_config_search_path(path) repo = ConfigRepository(config_search_path=config_search_path) ret = repo.get_group_options(group_name=config_path, results_filter=results_filter) assert ret == expected
def test_discovery() -> None: # Tests that this plugin can be discovered after Plugins.register is called plugin_name = ExampleRegisteredPlugin.__name__ assert plugin_name not in [ x.__name__ for x in Plugins.instance().discover(Plugin) ] register_example_plugin() assert plugin_name in [ x.__name__ for x in Plugins.instance().discover(Plugin) ]
def _print_plugins_profiling_info(self, top_n: int) -> None: assert log is not None stats = Plugins.instance().get_stats() if stats is None: return items = list(stats.modules_import_time.items()) # hide anything that took less than 5ms filtered = filter(lambda x: x[1] > 0.0005, items) sorted_items = sorted(filtered, key=lambda x: x[1], reverse=True) top_n = max(len(sorted_items), top_n) box: List[List[str]] = [["Module", "Sec"]] for item in sorted_items[0:top_n]: box.append([item[0], f"{item[1]:.3f}"]) padding = get_column_widths(box) log.debug("") self._log_header(header="Profiling information", filler="*") self._log_header( header=f"Total plugins scan time : {stats.total_time:.3f} seconds", filler="-", ) header = f"| {box[0][0].ljust(padding[0])} | {box[0][1].ljust(padding[1])} |" self._log_header(header=header, filler="-") del box[0] for row in box: a = row[0].ljust(padding[0]) b = row[1].ljust(padding[1]) log.debug(f"| {a} | {b} |") self._log_footer(header=header, filler="-")
def multirun( self, config_name: Optional[str], task_function: TaskFunction, overrides: List[str], with_log_configuration: bool = True, ) -> Any: # Initial config is loaded without strict (individual job configs may have strict). cfg = self.compose_config( config_name=config_name, overrides=overrides, strict=False, with_log_configuration=with_log_configuration, run_mode=RunMode.MULTIRUN, ) HydraConfig.instance().set_config(cfg) sweeper = Plugins.instance().instantiate_sweeper( config=cfg, config_loader=self.config_loader, task_function=task_function) task_overrides = OmegaConf.to_container(cfg.hydra.overrides.task, resolve=False) assert isinstance(task_overrides, list) return sweeper.sweep(arguments=task_overrides)
def multirun( self, config_name: Optional[str], task_function: TaskFunction, overrides: List[str], with_log_configuration: bool = True, ) -> Any: cfg = self.compose_config( config_name=config_name, overrides=overrides, with_log_configuration=with_log_configuration, run_mode=RunMode.MULTIRUN, ) callbacks = Callbacks(cfg) callbacks.on_multirun_start(config=cfg, config_name=config_name) sweeper = Plugins.instance().instantiate_sweeper( config=cfg, hydra_context=HydraContext(config_loader=self.config_loader, callbacks=callbacks), task_function=task_function, ) task_overrides = OmegaConf.to_container(cfg.hydra.overrides.task, resolve=False) assert isinstance(task_overrides, list) ret = sweeper.sweep(arguments=task_overrides) callbacks.on_multirun_end(config=cfg, config_name=config_name) return ret
def test_discovery() -> None: """ Tests that this plugin can be discovered via the plugins subsystem when looking for Sweeper :return: """ assert AxSweeper.__name__ in [ x.__name__ for x in Plugins.instance().discover(Sweeper) ]
def test_skipped_imports(tmpdir: Path) -> None: # Tests that modules starting with an "_" (but not "__") are skipped discovered_plugins = [ x.__name__ for x in Plugins.instance().discover(Plugin) ] assert "HiddenTestPlugin" not in discovered_plugins assert "NotHiddenTestPlugin" in discovered_plugins
def setup( self, config: DictConfig, config_loader: ConfigLoader, task_function: TaskFunction, ) -> None: self.config = config self.launcher = Plugins.instance().instantiate_launcher( config=config, config_loader=config_loader, task_function=task_function )
def test_number_of_imports(tmpdir: Path) -> None: os.environ["TMP_FILE"] = str(tmpdir / "import.log") # Tests that this plugin can be discovered via the plugins subsystem when looking at all Plugins assert "DiscoveryTestPlugin" in [ x.__name__ for x in Plugins.instance().discover(Plugin) ] with Path(os.environ["TMP_FILE"]) as f: txt = str(f.read_text()) assert txt.split("\n").count("imported") == 1
def setup( self, *, hydra_context: HydraContext, task_function: TaskFunction, config: DictConfig, ) -> None: self.config = config self.hydra_context = hydra_context self.launcher = Plugins.instance().instantiate_launcher( config=config, hydra_context=hydra_context, task_function=task_function ) self.sweep_dir = config.hydra.sweep.dir
def setup( self, config: DictConfig, config_loader: ConfigLoader, task_function: TaskFunction, ) -> None: self.job_idx = 0 self.config = config self.config_loader = config_loader self.launcher = Plugins.instance().instantiate_launcher( config=config, config_loader=config_loader, task_function=task_function ) self.sweep_dir = config.hydra.sweep.dir
def setup( self, config, config_loader, task_function, ): self.job_idx = 0 self.config = config self.config_loader = config_loader self.launcher = Plugins.instance().instantiate_launcher( config=config, config_loader=config_loader, task_function=task_function)
def setup( self, *, hydra_context: HydraContext, task_function: TaskFunction, config: DictConfig, ) -> None: self.job_idx = 0 self.config = config self.hydra_context = hydra_context self.launcher = Plugins.instance().instantiate_launcher( hydra_context=hydra_context, task_function=task_function, config=config )
def setup( self, config: DictConfig, config_loader: ConfigLoader, task_function: TaskFunction, ) -> None: from hydra.core.plugins import Plugins self.config_loader = config_loader self.config = config self.launcher = Plugins.instance().instantiate_launcher( config=config, config_loader=config_loader, task_function=task_function )
def get_shell_to_plugin_map( config_loader: ConfigLoader, ) -> DefaultDict[str, List[CompletionPlugin]]: shell_to_plugin: DefaultDict[str, List[CompletionPlugin]] = defaultdict(list) for clazz in Plugins.instance().discover(CompletionPlugin): assert issubclass(clazz, CompletionPlugin) plugin = clazz(config_loader) shell_to_plugin[plugin.provides()].append(plugin) for shell, plugins in shell_to_plugin.items(): if len(plugins) > 1: lst = ",".join([type(plugin).__name__ for plugin in plugins]) raise ValueError(f"Multiple plugins installed for {shell} : {lst}") return shell_to_plugin
def test_setup_plugins( monkeypatch: Any, plugin: Union[Launcher, Sweeper], config: DictConfig ) -> None: task_function = Mock(spec=TaskFunction) config_loader = ConfigLoaderImpl(config_search_path=create_config_search_path(None)) hydra_context = HydraContext(config_loader=config_loader, callbacks=Callbacks()) plugin_instance = Plugins.instance() monkeypatch.setattr(Plugins, "check_usage", lambda _: None) monkeypatch.setattr(plugin_instance, "_instantiate", lambda _: plugin) msg = "setup() got an unexpected keyword argument 'hydra_context'" with raises(TypeError, match=re.escape(msg)): if isinstance(plugin, Launcher): Plugins.instance().instantiate_launcher( hydra_context=hydra_context, task_function=task_function, config=config, ) else: Plugins.instance().instantiate_sweeper( hydra_context=hydra_context, task_function=task_function, config=config, )
def _get_completion_help() -> str: from hydra.core.plugins import Plugins from hydra.plugins.completion_plugin import CompletionPlugin completion_plugins = Plugins.instance().discover(CompletionPlugin) completion_info: List[str] = [] for plugin_cls in completion_plugins: assert issubclass(plugin_cls, CompletionPlugin) for cmd in ["install", "uninstall"]: head = f"{plugin_cls.provides().capitalize()} - {cmd.capitalize()}:" completion_info.append(head) completion_info.append(plugin_cls.help(cmd).format(_get_exec_command())) completion_info.append("") completion_help = "\n".join([f" {x}" if x else x for x in completion_info]) return completion_help
def setup( self, *, hydra_context: HydraContext, task_function: TaskFunction, config: DictConfig, ) -> None: from hydra.core.plugins import Plugins self.hydra_context = hydra_context self.config = config self.launcher = Plugins.instance().instantiate_launcher( hydra_context=hydra_context, task_function=task_function, config=config, )
def create_config_search_path(search_path_dir: Optional[str]) -> ConfigSearchPath: from hydra.core.plugins import Plugins from hydra.plugins.search_path_plugin import SearchPathPlugin search_path = ConfigSearchPathImpl() search_path.append("hydra", "pkg://hydra.conf") if search_path_dir is not None: search_path.append("main", search_path_dir) search_path_plugins = Plugins.instance().discover(SearchPathPlugin) for spp in search_path_plugins: plugin = spp() assert isinstance(plugin, SearchPathPlugin) plugin.manipulate_search_path(search_path) search_path.append("schema", "structured://") return search_path
def multirun( self, config_name: Optional[str], task_function: TaskFunction, overrides: List[str], ) -> Any: # Initial config is loaded without strict (individual job configs may have strict). cfg = self.compose_config( config_name=config_name, overrides=overrides, strict=False, with_log_configuration=True, ) HydraConfig.instance().set_config(cfg) sweeper = Plugins.instance().instantiate_sweeper( config=cfg, config_loader=self.config_loader, task_function=task_function ) task_overrides = cfg.hydra.overrides.task return sweeper.sweep(arguments=task_overrides)
def test_discovery() -> None: # Tests that this plugin can be discovered via the plugins subsystem when looking for Launchers assert JoblibLauncher.__name__ in [ x.__name__ for x in Plugins.instance().discover(Launcher) ]
def test_register_bad_plugin() -> None: class NotAPlugin: ... with raises(ValueError, match="Not a valid Hydra Plugin"): Plugins.instance().register(NotAPlugin) # type: ignore
def test_discover(plugin_type: Type[Plugin], expected: List[str]) -> None: plugins = Plugins.instance().discover(plugin_type) expected_classes = [get_class(c) for c in expected] for ex in expected_classes: assert ex in plugins